diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..8ad53ebb --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,72 @@ +version: 2 +jobs: + build: + branches: + only: + - master + - develop + + docker: + - image: ubuntu:trusty + + environment: + WM_NCOMPPROCS: 2 + + working_directory: /root/CFDEM/CFDEMcoupling + + steps: + - run: + name: Install package dependencies + command: sudo apt-get update && sudo apt-get install -y build-essential cmake openmpi-bin libopenmpi-dev python-dev git bc + + - run: + name: Make project and user dir + command: mkdir -p /root/CFDEM/CFDEMcoupling && mkdir -p /root/CFDEM/-4.1 + + - checkout: + path: /root/CFDEM/CFDEMcoupling + + - run: + name: Add OpenFOAM package repository + command: sudo apt-get install -y software-properties-common wget apt-transport-https && sudo add-apt-repository http://dl.openfoam.org/ubuntu && sudo sh -c "wget -O - http://dl.openfoam.org/gpg.key | apt-key add -" + + - run: + name: Install OpenFOAM 4.1 + command: sudo apt-get update && sudo apt-get -y install openfoam4 + + - run: + name: Clone LIGGGHTS repository + command: git clone https://github.com/ParticulateFlow/LIGGGHTS-PFM.git /root/CFDEM/LIGGGHTS + + - run: + name: Build LIGGGHTS + command: > + shopt -s expand_aliases && + source /opt/openfoam4/etc/bashrc && + source /root/CFDEM/CFDEMcoupling/etc/bashrc && + bash /root/CFDEM/CFDEMcoupling/etc/compileLIGGGHTS.sh + no_output_timeout: 30m + + - run: + name: Build CFDEMcoupling library + command: > + shopt -s expand_aliases && + source /opt/openfoam4/etc/bashrc && + source /root/CFDEM/CFDEMcoupling/etc/bashrc && + bash /root/CFDEM/CFDEMcoupling/etc/compileCFDEMcoupling_src.sh + + - run: + name: Build CFDEMcoupling solvers + command: > + shopt -s expand_aliases && + source /opt/openfoam4/etc/bashrc && + source /root/CFDEM/CFDEMcoupling/etc/bashrc && + bash /root/CFDEM/CFDEMcoupling/etc/compileCFDEMcoupling_sol.sh + + - run: + name: Build CFDEMcoupling utilities + command: > + shopt -s expand_aliases && + source /opt/openfoam4/etc/bashrc && + source /root/CFDEM/CFDEMcoupling/etc/bashrc && + bash /root/CFDEM/CFDEMcoupling/etc/compileCFDEMcoupling_uti.sh diff --git a/.gitignore b/.gitignore index b4b35554..2ac20489 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ log_* log.* *~ +*.swp +*.swo **/linux*Gcc*/ **/.vscode diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. diff --git a/README b/README deleted file mode 100755 index d0a970d3..00000000 --- a/README +++ /dev/null @@ -1,80 +0,0 @@ -/*---------------------------------------------------------------------------*\ - CFDEMcoupling - Open Source CFD-DEM coupling - - CFDEMcoupling is part of the CFDEMproject - www.cfdem.com - Christoph Goniva, christoph.goniva@cfdem.com - Copyright 2009-2012 JKU Linz - Copyright 2012-2015 DCS Computing GmbH, Linz - Copyright 2015- JKU Linz -------------------------------------------------------------------------------- -License - This file is part of CFDEMcoupling. - - CFDEMcoupling 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. - - CFDEMcoupling 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 CFDEMcoupling; if not, write to the Free Software Foundation, - Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Description - This code provides models and solvers to realize coupled CFD-DEM simulations - using LIGGGHTS and OpenFOAM. - Note: this code is not part of OpenFOAM (see DISCLAIMER). -\*---------------------------------------------------------------------------*/ - - -CFDEM(R) coupling provides an open source parallel coupled CFD-DEM framework -combining the strengths of the LIGGGHTS(R) DEM code and the Open Source -CFD package OpenFOAM(R)(*). The CFDEM(R)coupling toolbox allows to expand -standard CFD solvers of OpenFOAM(R)(*) to include a coupling to the DEM -code LIGGGHTS(R). In this toolbox the particle representation within the -CFD solver is organized by "cloud" classes. Key functionalities are organised -in sub-models (e.g. force models, data exchange models, etc.) which can easily -be selected and combined by dictionary settings. - -The coupled solvers run fully parallel on distributed-memory clusters. - -Features are: - -- its modular approach allows users to easily implement new models -- its MPI parallelization enables to use it for large scale problems -- the use of GIT allows to easily update to the latest version -- basic documentation is provided - -The file structure: - -- "src" directory including the source files of the coupling toolbox and models -- "applications" directory including the solver files for coupled CFD-DEM simulations -- "doc" directory including the documentation of CFDEM(R)coupling -- "tutorials" directory including basic tutorial cases showing the functionality - - - -Details on installation are given on the "www.cfdem.com" - -The functionality of this CFD-DEM framwork is described via "tutorial cases" showing -how to use different solvers and models. - -CFDEM(R)coupling stands for Computational Fluid Dynamics (CFD) - -Discrete Element Method (DEM) coupling. - -CFDEM(R)coupling is an open-source code, distributed freely under the terms of the -GNU Public License (GPL). - -Core development of CFDEM(R)coupling is done by -Christoph Goniva and Christoph Kloss, both at DCS Computing GmbH, 2012 - - -/*---------------------------------------------------------------------------*\ -(*) "OpenFOAM(R)" is a registered trade mark of OpenCFD Limited, a wholly owned subsidiary of the ESI Group. -This offering is not approved or endorsed by OpenCFD Limited, the producer of the OpenFOAM software and owner of the OPENFOAM® and OpenCFD® trade marks. -\*---------------------------------------------------------------------------*/ diff --git a/README.md b/README.md new file mode 100755 index 00000000..78a297fd --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# CFDEMcoupling + +CFDEM®coupling stands for Computational Fluid Dynamics (CFD) - Discrete Element Method (DEM) coupling. It combines the open source packages OpenFOAM® (CFD) and LIGGGHTS® (DEM) to simulate particle-laden flows. CFDEM®coupling is part of the [CFDEM®project](https://www.cfdem.com). + +[](https://circleci.com/gh/ParticulateFlow/CFDEMcoupling) +[](https://www.gnu.org/licenses/gpl-3.0.html) + +## Disclaimer + +> This is an academic adaptation of the CFDEM®coupling software package, released by the +[Department of Particulate Flow Modelling at Johannes Kepler University in Linz, Austria.](https://www.jku.at/pfm) +> LIGGGHTS® and CFDEM® are registered trademarks, and this offering is not approved or +endorsed by DCS Computing GmbH, the official producer of the LIGGGHTS® and CFDEM®coupling software. +> This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. + +## Features + +- Documentation and tutorials to get started +- A modular approach that allows for easy implementation of new models +- MPI parallelization for large scale problems + +## License + +[](https://www.gnu.org/licenses/gpl-3.0.html) + +- This software is distributed under the [GNU General Public License](https://opensource.org/licenses/GPL-3.0). +- Copyright © 2009- JKU Linz +- Copyright © 2012-2015 DCS Computing GmbH, Linz +- Some parts of CFDEM®coupling are based on OpenFOAM® and Copyright on these + parts is held by the OpenFOAM® Foundation (www.openfoam.org) + and potentially other parties. +- Some parts of CFDEM®coupling are contributed by other parties, which are + holding the Copyright. This is listed in each file of the distribution. diff --git a/applications/solvers/cfdemSolverRhoPimple/EEqn.H b/applications/solvers/cfdemSolverRhoPimple/EEqn.H index 08af6a05..022e933d 100644 --- a/applications/solvers/cfdemSolverRhoPimple/EEqn.H +++ b/applications/solvers/cfdemSolverRhoPimple/EEqn.H @@ -6,9 +6,6 @@ particleCloud.energyContributions(Qsource); particleCloud.energyCoefficients(QCoeff); - //thDiff=particleCloud.thermCondM().thermDiff(); - thCond=particleCloud.thermCondM().thermCond(); - addSource = fvc::ddt(rhoeps, K) + fvc::div(phi, K) + ( he.name() == "e" @@ -35,7 +32,6 @@ - Qsource - fvm::Sp(QCoeff/Cpv, he) // thermal conduction of the fluid with effective conductivity - // - fvm::laplacian(rhoeps*thDiff,he) - fvm::laplacian(voidfraction*thCond/Cpv,he) // + particle-fluid energy transfer due to work // + fluid energy dissipation due to shearing diff --git a/applications/solvers/cfdemSolverRhoPimple/createFields.H b/applications/solvers/cfdemSolverRhoPimple/createFields.H index 366cc1d0..35364cbd 100644 --- a/applications/solvers/cfdemSolverRhoPimple/createFields.H +++ b/applications/solvers/cfdemSolverRhoPimple/createFields.H @@ -58,10 +58,11 @@ Info<< "Reading thermophysical properties\n" << endl; "addSource", runTime.timeName(), mesh, - IOobject::MUST_READ, + IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), - mesh + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) ); Info<< "\nCreating fluid-particle heat flux field\n" << endl; @@ -94,21 +95,6 @@ Info<< "Reading thermophysical properties\n" << endl; dimensionedScalar("zero", dimensionSet(1,-1,-3,-1,0,0,0), 0.0) ); - /* Info<< "\nCreating thermal diffusivity field\n" << endl; - volScalarField thDiff - ( - IOobject - ( - "thDiff", - runTime.timeName(), - mesh, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - mesh, - dimensionedScalar("zero", dimensionSet(0,2,-1,0,0,0,0), 0.0) - ); - */ Info<< "\nCreating thermal conductivity field\n" << endl; volScalarField thCond ( @@ -117,11 +103,12 @@ Info<< "Reading thermophysical properties\n" << endl; "thCond", runTime.timeName(), mesh, - IOobject::NO_READ, + IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), mesh, - dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0) + dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0), + "zeroGradient" ); Info<< "\nCreating heat capacity field\n" << endl; diff --git a/applications/solvers/cfdemSolverRhoPimpleChem/EEqn.H b/applications/solvers/cfdemSolverRhoPimpleChem/EEqn.H index 5dfd1a5a..9a5f10b8 100644 --- a/applications/solvers/cfdemSolverRhoPimpleChem/EEqn.H +++ b/applications/solvers/cfdemSolverRhoPimpleChem/EEqn.H @@ -6,12 +6,11 @@ volScalarField& he = thermo.he(); particleCloud.energyContributions(Qsource); particleCloud.energyCoefficients(QCoeff); -thCond=particleCloud.thermCondM().thermCond(); Cpv = he.name() == "e" ? thermo.Cv() : thermo.Cp(); // correct source for the thermodynamic reference temperature -dimensionedScalar Tref("Tref", dimTemperature, T[0]-he[0]/(Cpv[0]+SMALL)); -Qsource += QCoeff*Tref; +// dimensionedScalar Tref("Tref", dimTemperature, T[0]-he[0]/(Cpv[0]+SMALL)); +// Qsource += QCoeff*Tref; fvScalarMatrix EEqn ( @@ -49,7 +48,13 @@ fvScalarMatrix EEqn thermo.correct(); - Info<< "T max/min : " << max(T).value() << " " << min(T).value() << endl; - Info << "he min/max : " << max(he).value() << " " << min(he).value() << endl; + Info << "Qsource :" << max(Qsource).value() << " " << min(Qsource).value() << endl; + Info << "QCoeff :" << max(QCoeff).value() << " " << min(QCoeff).value() << endl; + Info << "Cpv :" << max(Cpv).value() << " " << min(Cpv).value() << endl; + Info<< "T max/min : " << max(T).value() << " " << min(T).value() << endl; + Info << "he max/min : " << max(he).value() << " " << min(he).value() << endl; + particleCloud.clockM().start(31,"energySolve"); + particleCloud.solve(); + particleCloud.clockM().stop("energySolve"); } diff --git a/applications/solvers/cfdemSolverRhoPimpleChem/cfdemSolverRhoPimpleChem.C b/applications/solvers/cfdemSolverRhoPimpleChem/cfdemSolverRhoPimpleChem.C index 460d6a78..3947b48a 100644 --- a/applications/solvers/cfdemSolverRhoPimpleChem/cfdemSolverRhoPimpleChem.C +++ b/applications/solvers/cfdemSolverRhoPimpleChem/cfdemSolverRhoPimpleChem.C @@ -53,7 +53,6 @@ Description int main(int argc, char *argv[]) { -// #include "postProcess.H" #include "setRootCase.H" #include "createTime.H" #include "createMesh.H" @@ -62,7 +61,6 @@ int main(int argc, char *argv[]) #include "createRDeltaT.H" #include "createFields.H" - #include "createFieldRefs.H" #include "createFvOptions.H" #include "initContinuityErrs.H" diff --git a/applications/solvers/cfdemSolverRhoPimpleChem/createFields.H b/applications/solvers/cfdemSolverRhoPimpleChem/createFields.H index c1013203..6cbcfeeb 100644 --- a/applications/solvers/cfdemSolverRhoPimpleChem/createFields.H +++ b/applications/solvers/cfdemSolverRhoPimpleChem/createFields.H @@ -28,6 +28,8 @@ } volScalarField& p = thermo.p(); + const volScalarField& T = thermo.T(); + const volScalarField& psi = thermo.psi(); multivariateSurfaceInterpolationScheme::fieldTable fields; @@ -51,9 +53,6 @@ ); // kinematic fields - - - Info<< "Reading field U\n" << endl; volVectorField U ( @@ -82,18 +81,8 @@ mesh ); - volScalarField rhoeps - ( - IOobject - ( - "rhoeps", - runTime.timeName(), - mesh, - IOobject::MUST_READ, - IOobject::AUTO_WRITE - ), - rho*voidfraction - ); + volScalarField rhoeps ("rhoeps", rho*voidfraction); + Info<< "\nCreating fluid-particle heat flux field\n" << endl; volScalarField Qsource @@ -133,11 +122,12 @@ "thCond", runTime.timeName(), mesh, - IOobject::NO_READ, + IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), mesh, - dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0) + dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0), + "zeroGradient" ); Info<< "\nCreating heat capacity field\n" << endl; @@ -282,9 +272,18 @@ mesh, dimensionedScalar("zero",dimensionSet(0, -3, 0, 0, 1),0) ); + + volScalarField dSauter + ( + IOobject + ( + "dSauter", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero",dimensionSet(0, 1, 0, 0, 0,0,0),0) + ); //=============================== - - - - // singlePhaseTransportModel laminarTransport(U, phi); - diff --git a/applications/solvers/cfdemSolverRhoSimple/Make/files b/applications/solvers/cfdemSolverRhoSimple/Make/files deleted file mode 100644 index d9db0744..00000000 --- a/applications/solvers/cfdemSolverRhoSimple/Make/files +++ /dev/null @@ -1,3 +0,0 @@ -cfdemSolverRhoSimple.C - -EXE=$(CFDEM_APP_DIR)/cfdemSolverRhoSimple diff --git a/applications/solvers/rStatAnalysis/Make/files b/applications/solvers/rStatAnalysis/Make/files new file mode 100644 index 00000000..7f43b8f6 --- /dev/null +++ b/applications/solvers/rStatAnalysis/Make/files @@ -0,0 +1,3 @@ +rStatAnalysis.C + +EXE=$(CFDEM_APP_DIR)/rStatAnalysis diff --git a/applications/solvers/rStatAnalysis/Make/options b/applications/solvers/rStatAnalysis/Make/options new file mode 100644 index 00000000..f91d7947 --- /dev/null +++ b/applications/solvers/rStatAnalysis/Make/options @@ -0,0 +1,26 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + +EXE_INC = \ + -I$(CFDEM_OFVERSION_DIR) \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \ + -I$(LIB_SRC)/transportModels \ + -I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \ + -I$(CFDEM_SRC_DIR)/recurrence/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/derived/cfdemCloudRec \ + +EXE_LIBS = \ + -L$(CFDEM_LIB_DIR)\ + -lrecurrence \ + -lturbulenceModels \ + -lincompressibleTurbulenceModels \ + -lincompressibleTransportModels \ + -lfiniteVolume \ + -lmeshTools \ + -l$(CFDEM_LIB_NAME) \ + $(CFDEM_ADD_LIB_PATHS) \ +$(CFDEM_ADD_LIBS) diff --git a/applications/solvers/rStatAnalysis/createFields.H b/applications/solvers/rStatAnalysis/createFields.H new file mode 100644 index 00000000..e69de29b diff --git a/applications/solvers/rStatAnalysis/rStatAnalysis.C b/applications/solvers/rStatAnalysis/rStatAnalysis.C new file mode 100644 index 00000000..38356182 --- /dev/null +++ b/applications/solvers/rStatAnalysis/rStatAnalysis.C @@ -0,0 +1,67 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . + +Application + rStatAnalysis + +Description + Creates and analyzes a recurrence statistics + +\*---------------------------------------------------------------------------*/ + +// #include "fvCFD.H" +// #include "singlePhaseTransportModel.H" +// #include "turbulentTransportModel.H" +// #include "fvOptions.H" + +#include "recBase.H" +#include "recStatAnalysis.H" + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + #include "postProcess.H" + #include "setRootCase.H" + #include "createTime.H" + #include "createMesh.H" + #include "createControl.H" + + + recBase recurrenceBase(mesh); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info << "\nAnalyzing recurrence statistics\n" << endl; + + recurrenceBase.recStatA().init(); + recurrenceBase.recStatA().statistics(); + + Info << "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/solvers/rcfdemSolverBase/Make/files b/applications/solvers/rcfdemSolverBase/Make/files new file mode 100644 index 00000000..cceb4a66 --- /dev/null +++ b/applications/solvers/rcfdemSolverBase/Make/files @@ -0,0 +1,3 @@ +rcfdemSolverBase.C + +EXE=$(CFDEM_APP_DIR)/rcfdemSolverBase diff --git a/applications/solvers/rcfdemSolverBase/Make/options b/applications/solvers/rcfdemSolverBase/Make/options new file mode 100644 index 00000000..9443c2f8 --- /dev/null +++ b/applications/solvers/rcfdemSolverBase/Make/options @@ -0,0 +1,27 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + +EXE_INC = \ + -I$(CFDEM_OFVERSION_DIR) \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \ + -I$(LIB_SRC)/transportModels \ + -I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \ + -I$(CFDEM_SRC_DIR)/recurrence/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/derived/cfdemCloudRec \ + +EXE_LIBS = \ + -L$(CFDEM_LIB_DIR)\ + -lrecurrence \ + -lturbulenceModels \ + -lincompressibleTurbulenceModels \ + -lincompressibleTransportModels \ + -lfiniteVolume \ + -lmeshTools \ + -lfvOptions \ + -l$(CFDEM_LIB_NAME) \ + $(CFDEM_ADD_LIB_PATHS) \ +$(CFDEM_ADD_LIBS) diff --git a/applications/solvers/rcfdemSolverBase/createFields.H b/applications/solvers/rcfdemSolverBase/createFields.H new file mode 100644 index 00000000..2d002e5e --- /dev/null +++ b/applications/solvers/rcfdemSolverBase/createFields.H @@ -0,0 +1,125 @@ + // dummy fields + Info << "\nCreating dummy pressure and density fields\n" << endl; + volScalarField p + ( + IOobject + ( + "p", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh, + dimensionedScalar("p", dimensionSet(1, 2, -2, 0, 0), 1.0) + ); + + volScalarField rho + ( + IOobject + ( + "rho", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh, + dimensionedScalar("rho", dimensionSet(1, -3, 0, 0, 0), 1.0) + ); + + // recurrence fields + Info << "\nCreating recurrence fields.\n" << endl; + volVectorField URec + ( + IOobject + ( + "URec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + volScalarField voidfractionRec + ( + IOobject + ( + "voidfractionRec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + volVectorField UsRec + ( + IOobject + ( + "UsRec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + // calculated fields + Info << "\nCreating fields subject to calculation\n" << endl; + volScalarField voidfraction + ( + IOobject + ( + "voidfraction", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + voidfractionRec + ); + + volVectorField Us + ( + IOobject + ( + "Us", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + UsRec + ); + + // write fields for t=t_start + voidfraction.write(); + Us.write(); +//=============================== + + Info << "Calculating face flux field phi\n" << endl; + surfaceScalarField phiRec + ( + IOobject + ( + "phiRec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + linearInterpolate(URec*voidfractionRec) & mesh.Sf() + ); + phiRec.write(); + + singlePhaseTransportModel laminarTransport(URec, phiRec); + + autoPtr turbulence + ( + incompressible::turbulenceModel::New(URec, phiRec, laminarTransport) + ); diff --git a/applications/solvers/rcfdemSolverBase/rcfdemSolverBase.C b/applications/solvers/rcfdemSolverBase/rcfdemSolverBase.C new file mode 100644 index 00000000..734e7e8e --- /dev/null +++ b/applications/solvers/rcfdemSolverBase/rcfdemSolverBase.C @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger, Gerhard Holzinger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . + +Application + cfdemSolverRecurrence + +Description + Solves a transport equation for a passive scalar on a two-phase solution + Test-bed for a solver based on recurrence statistics + +Rules + Solution data to compute the recurrence statistics from, needs to + reside in $CASE_ROOT/dataBase + Time step data in dataBase needs to be evenly spaced in time + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" +#include "singlePhaseTransportModel.H" +#include "turbulentTransportModel.H" +#include "fvOptions.H" + +#include "cfdemCloudRec.H" +#include "recBase.H" +#include "recModel.H" + +#include "cfdemCloud.H" +#include "clockModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + #include "postProcess.H" + #include "setRootCase.H" + #include "createTime.H" + #include "createMesh.H" + #include "createControl.H" + #include "createFields.H" + #include "createFvOptions.H" + + cfdemCloudRec particleCloud(mesh); + recBase recurrenceBase(mesh); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info << "\nCalculating particle trajectories based on recurrence statistics\n" << endl; + + label recTimeIndex = 0; + scalar recTimeStep = recurrenceBase.recM().recTimeStep(); + scalar startTime = runTime.startTime().value(); + + while (runTime.run()) + { + runTime++; + + // do stuff (every lagrangian time step) + particleCloud.clockM().start(1,"Global"); + + Info << "Time = " << runTime.timeName() << nl << endl; + + particleCloud.clockM().start(2,"Coupling"); + + particleCloud.evolve(voidfraction,Us,URec); + + particleCloud.clockM().stop("Coupling"); + + + if ( runTime.timeOutputValue() - startTime - (recTimeIndex+1)*recTimeStep + 1.0e-5 > 0.0 ) + { + recurrenceBase.updateRecFields(); + #include "readFields.H" + recTimeIndex++; + } + + particleCloud.clockM().start(27,"Output"); + runTime.write(); + particleCloud.clockM().stop("Output"); + + particleCloud.clockM().stop("Global"); + + Info << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" + << " ClockTime = " << runTime.elapsedClockTime() << " s" + << nl << endl; + + } + + Info << "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/solvers/rcfdemSolverBase/readFields.H b/applications/solvers/rcfdemSolverBase/readFields.H new file mode 100644 index 00000000..262a9474 --- /dev/null +++ b/applications/solvers/rcfdemSolverBase/readFields.H @@ -0,0 +1,4 @@ +recurrenceBase.recM().exportVolScalarField("voidfraction",voidfractionRec); +recurrenceBase.recM().exportVolVectorField("U",URec); +recurrenceBase.recM().exportVolVectorField("Us",UsRec); +recurrenceBase.recM().exportSurfaceScalarField("phi",phiRec); \ No newline at end of file diff --git a/applications/solvers/rcfdemSolverCoupledHeattransfer/Make/files b/applications/solvers/rcfdemSolverCoupledHeattransfer/Make/files new file mode 100644 index 00000000..ddecf91a --- /dev/null +++ b/applications/solvers/rcfdemSolverCoupledHeattransfer/Make/files @@ -0,0 +1,3 @@ +rcfdemSolverCoupledHeattransfer.C + +EXE=$(CFDEM_APP_DIR)/rcfdemSolverCoupledHeattransfer diff --git a/applications/solvers/rcfdemSolverCoupledHeattransfer/Make/options b/applications/solvers/rcfdemSolverCoupledHeattransfer/Make/options new file mode 100644 index 00000000..9443c2f8 --- /dev/null +++ b/applications/solvers/rcfdemSolverCoupledHeattransfer/Make/options @@ -0,0 +1,27 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + +EXE_INC = \ + -I$(CFDEM_OFVERSION_DIR) \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \ + -I$(LIB_SRC)/transportModels \ + -I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \ + -I$(CFDEM_SRC_DIR)/recurrence/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/derived/cfdemCloudRec \ + +EXE_LIBS = \ + -L$(CFDEM_LIB_DIR)\ + -lrecurrence \ + -lturbulenceModels \ + -lincompressibleTurbulenceModels \ + -lincompressibleTransportModels \ + -lfiniteVolume \ + -lmeshTools \ + -lfvOptions \ + -l$(CFDEM_LIB_NAME) \ + $(CFDEM_ADD_LIB_PATHS) \ +$(CFDEM_ADD_LIBS) diff --git a/applications/solvers/rcfdemSolverCoupledHeattransfer/TEqImp.H b/applications/solvers/rcfdemSolverCoupledHeattransfer/TEqImp.H new file mode 100644 index 00000000..8c13a1e4 --- /dev/null +++ b/applications/solvers/rcfdemSolverCoupledHeattransfer/TEqImp.H @@ -0,0 +1,35 @@ + volScalarField rhoeps = rhoRec*voidfractionRec; + + particleCloud.energyContributions(Qsource); + + particleCloud.energyCoefficients(QCoeff); + + //K = 0.5*magSqr(URec); + + addSource = fvc::div(phiRec/fvc::interpolate(rhoRec), pRec); + // main contribution due to gas expansion, not due to transport of kinetic energy + // fvc::ddt(rhoeps, K) + fvc::div(phiRec, K) + + fvScalarMatrix TEqn = + ( + fvm::ddt(rhoeps, T) + + fvm::div(phiRec, T) + + addSource/Cv + - fvm::laplacian(voidfractionRec*thCond/Cv, T) + - Qsource/Cv + - fvm::Sp(QCoeff/Cv, T) + == + fvOptions(rhoeps, T) // no fvOptions support yet + ); + + fvOptions.constrain(TEqn); // no fvOptions support yet + + TEqn.solve(); + + particleCloud.clockM().start(31,"postFlow"); + counter++; + + if((counter - couplingSubStep) % dtDEM2dtCFD == 0) + particleCloud.postFlow(); + + particleCloud.clockM().stop("postFlow"); diff --git a/applications/solvers/rcfdemSolverCoupledHeattransfer/createFields.H b/applications/solvers/rcfdemSolverCoupledHeattransfer/createFields.H new file mode 100644 index 00000000..4fe8e7b1 --- /dev/null +++ b/applications/solvers/rcfdemSolverCoupledHeattransfer/createFields.H @@ -0,0 +1,230 @@ + // dummy fields + Info << "\nCreating dummy pressure field\n" << endl; + volScalarField pRec + ( + IOobject + ( + "pRec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-2,0,0,0,0), 0.0) + ); + + // recurrence fields + Info << "\nCreating recurrence fields.\n" << endl; + + volScalarField rhoRec + ( + IOobject + ( + "rhoRec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1, -3, 0, 0, 0), 1.0) + ); + + volVectorField URec + ( + IOobject + ( + "URec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedVector("zero", dimensionSet(0, 1, -1, 0, 0), vector::zero) + ); + + volScalarField voidfractionRec + ( + IOobject + ( + "voidfractionRec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) + ); + + volVectorField UsRec + ( + IOobject + ( + "UsRec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedVector("zero", dimensionSet(0, 1, -1, 0, 0), vector::zero) + ); + + // heat transfer fields + Info << "\nCreating heat transfer fields.\n" << endl; + + volScalarField Qsource + ( + IOobject + ( + "Qsource", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) + ); + + volScalarField QCoeff + ( IOobject + ( + "QCoeff", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,-1,0,0,0), 0.0) + ); + + volScalarField thCond + ( + IOobject + ( + "thCond", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0), + "zeroGradient" + ); + + volScalarField T + ( + IOobject + ( + "T", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + // calculated fields + Info << "\nCreating fields subject to calculation\n" << endl; + volScalarField voidfraction + ( + IOobject + ( + "voidfraction", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + voidfractionRec + ); + + volVectorField Us + ( + IOobject + ( + "Us", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + UsRec + ); + + // write fields for t=t_start + voidfraction.write(); + Us.write(); +//=============================== + + + Info << "Calculating face flux field phiRec\n" << endl; + surfaceScalarField phiRec + ( + IOobject + ( + "phiRec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,0,-1,0,0,0,0), 0.0) + ); + phiRec.write(); + + + Info << "Creating dummy turbulence model\n" << endl; + singlePhaseTransportModel laminarTransport(URec, phiRec); + + autoPtr turbulence + ( + incompressible::turbulenceModel::New(URec, phiRec, laminarTransport) + ); + + + const IOdictionary& transportProps = mesh.lookupObject("transportProperties"); + dimensionedScalar molMass(transportProps.lookup("molM")); + // need to scale R down with 1e3 because return value of RR in g, not kg + dimensionedScalar R("R",dimensionSet(0,2,-2,-1,0,0,0),Foam::constant::thermodynamic::RR / (1e3*molMass.value())); + Info << "specific gas constant R = " << R << endl; + + dimensionedScalar Cv(transportProps.lookup("Cv")); + + + volScalarField addSource + ( + IOobject + ( + "addSource", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) + ); + + + // place to put weight functions + IOdictionary weightDict + ( + IOobject + ( + "weightDict", + runTime.constant(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE + ) + ); + weightDict.add("weights",scalarList(1,1.0)); diff --git a/applications/solvers/rcfdemSolverCoupledHeattransfer/rcfdemSolverCoupledHeattransfer.C b/applications/solvers/rcfdemSolverCoupledHeattransfer/rcfdemSolverCoupledHeattransfer.C new file mode 100644 index 00000000..1d128ac6 --- /dev/null +++ b/applications/solvers/rcfdemSolverCoupledHeattransfer/rcfdemSolverCoupledHeattransfer.C @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . + +Application + rcfdemSolverHeattransfer + +Description + Solves heat transfer between fluid and particles based on rCFD + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" +#include "fvOptions.H" +#include "singlePhaseTransportModel.H" +#include "turbulentTransportModel.H" +#include "cfdemCloudRec.H" +#include "recBase.H" +#include "recModel.H" +#include "recPath.H" + +#include "cfdemCloudEnergy.H" +#include "clockModel.H" +#include "thermCondModel.H" +#include "energyModel.H" + + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + #include "postProcess.H" + #include "setRootCase.H" + #include "createTime.H" + #include "createMesh.H" + #include "createControl.H" + #include "createFields.H" + #include "createFvOptions.H" + + cfdemCloudRec particleCloud(mesh); + recBase recurrenceBase(mesh); + #include "updateFields.H" + #include "updateRho.H" + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info << "\nCalculating particle trajectories based on recurrence statistics\n" << endl; + + label recTimeIndex = 0; + scalar recTimeStep = recurrenceBase.recM().recTimeStep(); + scalar startTime = runTime.startTime().value(); + + // control coupling behavior in case of substepping + // assumes constant timestep size + label counter = 0; + label couplingSubStep = recurrenceBase.couplingSubStep(); + double dtProp = particleCloud.dataExchangeM().couplingTime() / runTime.deltaTValue(); + label dtDEM2dtCFD = int(dtProp + 0.5); + Info << "deltaT_DEM / deltaT_CFD = " << dtDEM2dtCFD << endl; + if (dtDEM2dtCFD > 1) + Info << "coupling at substep " << couplingSubStep << endl; + + + while (runTime.run()) + { + runTime++; + + // do stuff (every lagrangian time step) + particleCloud.clockM().start(1,"Global"); + + Info << "Time = " << runTime.timeName() << nl << endl; + + particleCloud.clockM().start(2,"Coupling"); + + particleCloud.evolve(voidfraction,Us,URec); + + particleCloud.clockM().stop("Coupling"); + + particleCloud.clockM().start(26,"Flow"); + #include "updateRho.H" + #include "TEqImp.H" + particleCloud.clockM().stop("Flow"); + + particleCloud.clockM().start(32,"ReadFields"); + if ( runTime.timeOutputValue() - startTime - (recTimeIndex+1)*recTimeStep + 1.0e-5 > 0.0 ) + { + recurrenceBase.updateRecFields(); + #include "updateFields.H" + recTimeIndex++; + } + particleCloud.clockM().stop("ReadFields"); + + particleCloud.clockM().start(33,"Output"); + runTime.write(); + particleCloud.clockM().stop("Output"); + + particleCloud.clockM().stop("Global"); + + Info << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" + << " ClockTime = " << runTime.elapsedClockTime() << " s" + << nl << endl; + + } + + Info << "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/solvers/rcfdemSolverCoupledHeattransfer/updateFields.H b/applications/solvers/rcfdemSolverCoupledHeattransfer/updateFields.H new file mode 100644 index 00000000..8f21eaef --- /dev/null +++ b/applications/solvers/rcfdemSolverCoupledHeattransfer/updateFields.H @@ -0,0 +1,38 @@ +// get current weights for various databases + +// A: triggered over current value of boundary field +// word boundaryName = "inlet"; +// label myinlet = mesh.boundary().findPatchID(boundaryName); +// label startIndex = mesh.boundary()[boundaryName].start(); + +// B: explicitly define weights + +scalarList wList(weightDict.lookupOrDefault("weights",scalarList(1,0.0))); + +recurrenceBase.recP().updateIntervalWeights(wList); + +// is it neccessary to extend recurrence path? +if(recurrenceBase.recM().endOfPath()) +{ + recurrenceBase.extendPath(); +} + +recurrenceBase.recM().exportVolScalarField("voidfraction",voidfractionRec); +recurrenceBase.recM().exportVolScalarField("p",pRec); +recurrenceBase.recM().exportVolVectorField("Us",UsRec); +recurrenceBase.recM().exportSurfaceScalarField("phi",phiRec); + +Info << "current database weights: = " << wList << endl; +Info << "current database: " << recurrenceBase.recM().currDataBase() << endl; +for(int i=0;i(mesh.lookupObject ("NuField"))); + recurrenceBase.recM().exportVolScalarField("NuField",NuField); +} + diff --git a/applications/solvers/rcfdemSolverCoupledHeattransfer/updateRho.H b/applications/solvers/rcfdemSolverCoupledHeattransfer/updateRho.H new file mode 100644 index 00000000..63c7da64 --- /dev/null +++ b/applications/solvers/rcfdemSolverCoupledHeattransfer/updateRho.H @@ -0,0 +1 @@ +rhoRec = pRec / (T * R); \ No newline at end of file diff --git a/applications/solvers/rcfdemSolverHeattransfer/Make/files b/applications/solvers/rcfdemSolverHeattransfer/Make/files new file mode 100644 index 00000000..cfbe9475 --- /dev/null +++ b/applications/solvers/rcfdemSolverHeattransfer/Make/files @@ -0,0 +1,3 @@ +rcfdemSolverHeattransfer.C + +EXE=$(CFDEM_APP_DIR)/rcfdemSolverHeattransfer diff --git a/applications/solvers/rcfdemSolverHeattransfer/Make/options b/applications/solvers/rcfdemSolverHeattransfer/Make/options new file mode 100644 index 00000000..9443c2f8 --- /dev/null +++ b/applications/solvers/rcfdemSolverHeattransfer/Make/options @@ -0,0 +1,27 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + +EXE_INC = \ + -I$(CFDEM_OFVERSION_DIR) \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \ + -I$(LIB_SRC)/transportModels \ + -I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \ + -I$(CFDEM_SRC_DIR)/recurrence/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/derived/cfdemCloudRec \ + +EXE_LIBS = \ + -L$(CFDEM_LIB_DIR)\ + -lrecurrence \ + -lturbulenceModels \ + -lincompressibleTurbulenceModels \ + -lincompressibleTransportModels \ + -lfiniteVolume \ + -lmeshTools \ + -lfvOptions \ + -l$(CFDEM_LIB_NAME) \ + $(CFDEM_ADD_LIB_PATHS) \ +$(CFDEM_ADD_LIBS) diff --git a/applications/solvers/rcfdemSolverHeattransfer/TEqImp.H b/applications/solvers/rcfdemSolverHeattransfer/TEqImp.H new file mode 100644 index 00000000..104c3d87 --- /dev/null +++ b/applications/solvers/rcfdemSolverHeattransfer/TEqImp.H @@ -0,0 +1,40 @@ + volScalarField rhoeps = rhoRec*voidfractionRec; + + particleCloud.energyContributions(Qsource); + + particleCloud.energyCoefficients(QCoeff); + + K = 0.5*magSqr(URec); + + addSource = fvc::ddt(rhoeps, K) + fvc::div(phiRec, K) + + fvc::div + ( + fvc::absolute(phiRec/fvc::interpolate(rhoRec), voidfractionRec*URec), pRec + ); + + + fvScalarMatrix TEqn = + ( + fvm::ddt(rhoeps, T) + + fvm::div(phiRec, T) + + addSource/Cv + - fvm::laplacian(voidfractionRec*thCond/Cv, T) + - Qsource/Cv + - fvm::Sp(QCoeff/Cv, T) + == + fvOptions(rhoeps, T) // no fvOptions support yet + ); + + //TEqn.relax(relaxCoeff); + + fvOptions.constrain(TEqn); // no fvOptions support yet + + TEqn.solve(); + + particleCloud.clockM().start(31,"postFlow"); + counter++; + + if((counter - couplingSubStep) % dtDEM2dtCFD == 0) + particleCloud.postFlow(); + + particleCloud.clockM().stop("postFlow"); diff --git a/applications/solvers/rcfdemSolverHeattransfer/createFields.H b/applications/solvers/rcfdemSolverHeattransfer/createFields.H new file mode 100644 index 00000000..cade4a1a --- /dev/null +++ b/applications/solvers/rcfdemSolverHeattransfer/createFields.H @@ -0,0 +1,206 @@ + // dummy fields + Info << "\nCreating dummy pressure field\n" << endl; + volScalarField pRec + ( + IOobject + ( + "pRec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + // recurrence fields + Info << "\nCreating recurrence fields.\n" << endl; + + volScalarField rhoRec + ( + IOobject + ( + "rhoRec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh//, + //dimensionedScalar("rhoRec", dimensionSet(1, -3, 0, 0, 0), 1.0) + ); + + volVectorField URec + ( + IOobject + ( + "URec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + volScalarField voidfractionRec + ( + IOobject + ( + "voidfractionRec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + volVectorField UsRec + ( + IOobject + ( + "UsRec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + // heat transfer fields + Info << "\nCreating heat transfer fields.\n" << endl; + + volScalarField Qsource + ( + IOobject + ( + "Qsource", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) + ); + + volScalarField QCoeff + ( + IOobject + ( + "QCoeff", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,-1,0,0,0), 0.0) + ); + + volScalarField thCond + ( + IOobject + ( + "thCond", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0), + "zeroGradient" + ); + + volScalarField T + ( + IOobject + ( + "T", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + // calculated fields + Info << "\nCreating fields subject to calculation\n" << endl; + volScalarField voidfraction + ( + IOobject + ( + "voidfraction", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + voidfractionRec + ); + + volVectorField Us + ( + IOobject + ( + "Us", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + UsRec + ); + + // write fields for t=t_start + voidfraction.write(); + Us.write(); +//=============================== + + + Info << "Calculating face flux field phiRec\n" << endl; + surfaceScalarField phiRec + ( + IOobject + ( + "phiRec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + linearInterpolate(URec*voidfractionRec*rhoRec) & mesh.Sf() + ); + phiRec.write(); + + + singlePhaseTransportModel laminarTransport(URec, phiRec); + + autoPtr turbulence + ( + incompressible::turbulenceModel::New(URec, phiRec, laminarTransport) + ); + + const IOdictionary& transportProps = mesh.lookupObject("transportProperties"); + dimensionedScalar Cv(transportProps.lookup("Cv")); + + volScalarField addSource + ( + IOobject + ( + "addSource", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) + ); + + Info << "Creating field kinetic energy K\n" << endl; + volScalarField K("K", 0.5*magSqr(URec)); diff --git a/applications/solvers/rcfdemSolverHeattransfer/rcfdemSolverHeattransfer.C b/applications/solvers/rcfdemSolverHeattransfer/rcfdemSolverHeattransfer.C new file mode 100644 index 00000000..7fa36bff --- /dev/null +++ b/applications/solvers/rcfdemSolverHeattransfer/rcfdemSolverHeattransfer.C @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . + +Application + rcfdemSolverHeattransfer + +Description + Solves heat transfer between fluid and particles based on rCFD + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" +#include "singlePhaseTransportModel.H" +#include "turbulentTransportModel.H" +#include "fvOptions.H" + +#include "cfdemCloudRec.H" +#include "recBase.H" +#include "recModel.H" + +#include "cfdemCloudEnergy.H" +#include "clockModel.H" +#include "thermCondModel.H" +#include "energyModel.H" + + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + #include "postProcess.H" + #include "setRootCase.H" + #include "createTime.H" + #include "createMesh.H" + #include "createControl.H" + #include "createFields.H" + #include "createFvOptions.H" + + cfdemCloudRec particleCloud(mesh); + recBase recurrenceBase(mesh); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info << "\nCalculating particle trajectories based on recurrence statistics\n" << endl; + + label recTimeIndex = 0; + scalar recTimeStep = recurrenceBase.recM().recTimeStep(); + scalar startTime = runTime.startTime().value(); + + // control coupling behavior in case of substepping + // assumes constant timestep size + label counter = 0; + label couplingSubStep = recurrenceBase.couplingSubStep();//5;//3; + double dtProp = particleCloud.dataExchangeM().couplingTime() / runTime.deltaTValue(); + label dtDEM2dtCFD = int(dtProp + 0.5); + Info << "deltaT_DEM / deltaT_CFD = " << dtDEM2dtCFD << endl; + if (dtDEM2dtCFD > 1) + Info << "coupling at substep " << couplingSubStep << endl; + + + while (runTime.run()) + { + runTime++; + + // do stuff (every lagrangian time step) + particleCloud.clockM().start(1,"Global"); + + Info << "Time = " << runTime.timeName() << nl << endl; + + particleCloud.clockM().start(2,"Coupling"); + + particleCloud.evolve(voidfraction,Us,URec); + + particleCloud.clockM().stop("Coupling"); + + particleCloud.clockM().start(26,"Flow"); + #include "TEqImp.H" + particleCloud.clockM().stop("Flow"); + + particleCloud.clockM().start(32,"ReadFields"); + if ( runTime.timeOutputValue() - startTime - (recTimeIndex+1)*recTimeStep + 1.0e-5 > 0.0 ) + { + recurrenceBase.updateRecFields(); + #include "updateFields.H" + recTimeIndex++; + } + particleCloud.clockM().stop("ReadFields"); + + particleCloud.clockM().start(33,"Output"); + runTime.write(); + particleCloud.clockM().stop("Output"); + + particleCloud.clockM().stop("Global"); + + Info << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" + << " ClockTime = " << runTime.elapsedClockTime() << " s" + << nl << endl; + + } + + Info << "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/solvers/rcfdemSolverHeattransfer/updateFields.H b/applications/solvers/rcfdemSolverHeattransfer/updateFields.H new file mode 100644 index 00000000..5e9a8ab1 --- /dev/null +++ b/applications/solvers/rcfdemSolverHeattransfer/updateFields.H @@ -0,0 +1,14 @@ +recurrenceBase.recM().exportVolScalarField("voidfraction",voidfractionRec); +recurrenceBase.recM().exportVolScalarField("rho",rhoRec); +recurrenceBase.recM().exportVolScalarField("p",pRec); +recurrenceBase.recM().exportVolVectorField("Us",UsRec); +recurrenceBase.recM().exportVolVectorField("U",URec); +recurrenceBase.recM().exportSurfaceScalarField("phi",phiRec); + +{ + volScalarField& NuField(const_cast(mesh.lookupObject ("NuField"))); + recurrenceBase.recM().exportVolScalarField("NuField",NuField); +} + + +#include "updateRho.H" \ No newline at end of file diff --git a/applications/solvers/rcfdemSolverHeattransfer/updateRho.H b/applications/solvers/rcfdemSolverHeattransfer/updateRho.H new file mode 100644 index 00000000..159a8654 --- /dev/null +++ b/applications/solvers/rcfdemSolverHeattransfer/updateRho.H @@ -0,0 +1,32 @@ +// work-around for transient properties +// needs to be specified for each case + +// case 1 + +forAll(rhoRec,cellI) +{ + if (mesh.C()[cellI].z() < 0.00228) + rhoRec[cellI] = 1.18+(1.085-1.18)*Foam::exp(-0.065*runTime.timeOutputValue()); + else if (mesh.C()[cellI].z() < 0.00456) + rhoRec[cellI] = 1.18+(1.01-1.18)*Foam::exp(-0.05*runTime.timeOutputValue()); + else if (mesh.C()[cellI].z() < 0.00684) + rhoRec[cellI] = 1.18+(0.98-1.18)*Foam::exp(-0.0425*runTime.timeOutputValue()); + else + rhoRec[cellI] = 1.18+(0.955-1.18)*Foam::exp(-0.0425*runTime.timeOutputValue()); +} + + +// case 2 +/* +forAll(rhoRec,cellI) +{ + if (mesh.C()[cellI].z() < 0.00228) + rhoRec[cellI] = 1.18+(1.115-1.18)*Foam::exp(-0.065*runTime.timeOutputValue()); + else if (mesh.C()[cellI].z() < 0.00456) + rhoRec[cellI] = 1.18+(1.04-1.18)*Foam::exp(-0.05*runTime.timeOutputValue()); + else if (mesh.C()[cellI].z() < 0.00684) + rhoRec[cellI] = 1.18+(1.005-1.18)*Foam::exp(-0.0425*runTime.timeOutputValue()); + else + rhoRec[cellI] = 1.18+(0.96-1.18)*Foam::exp(-0.0425*runTime.timeOutputValue()); +} +*/ \ No newline at end of file diff --git a/applications/solvers/cfdemSolverRhoSimple/EEqn.H b/applications/solvers/rcfdemSolverRhoSteadyPimple/EEqn.H similarity index 77% rename from applications/solvers/cfdemSolverRhoSimple/EEqn.H rename to applications/solvers/rcfdemSolverRhoSteadyPimple/EEqn.H index 930f66e2..d9b32f48 100644 --- a/applications/solvers/cfdemSolverRhoSimple/EEqn.H +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/EEqn.H @@ -6,9 +6,6 @@ particleCloud.energyContributions(Qsource); particleCloud.energyCoefficients(QCoeff); - //thDiff=particleCloud.thermCondM().thermDiff(); - thCond=particleCloud.thermCondM().thermCond(); - addSource = ( he.name() == "e" @@ -16,7 +13,7 @@ fvc::div(phi, K) + fvc::div ( - fvc::absolute(phi/fvc::interpolate(rho), voidfraction*U), + fvc::absolute(phi/fvc::interpolate(rho), voidfractionRec*U), p, "div(phiv,p)" ) @@ -25,9 +22,6 @@ Cpv = he.name() == "e" ? thermo.Cv() : thermo.Cp(); - // correct source for the thermodynamic reference temperature - dimensionedScalar Tref("Tref", dimTemperature, T[0]-he[0]/(Cpv[0]+SMALL)); - Qsource += QCoeff*Tref; fvScalarMatrix EEqn ( @@ -35,12 +29,12 @@ + addSource - Qsource - fvm::Sp(QCoeff/Cpv, he) - - fvm::laplacian(voidfraction*thCond/Cpv,he) + // - fvm::laplacian(voidfractionRec*kf/Cpv,he) + - fvm::laplacian(voidfractionRec*thCond/Cpv,he) == fvOptions(rho, he) ); - EEqn.relax(); fvOptions.constrain(EEqn); diff --git a/applications/solvers/rcfdemSolverRhoSteadyPimple/Make/files b/applications/solvers/rcfdemSolverRhoSteadyPimple/Make/files new file mode 100644 index 00000000..fac2cca3 --- /dev/null +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/Make/files @@ -0,0 +1,3 @@ +rcfdemSolverRhoSteadyPimple.C + +EXE=$(CFDEM_APP_DIR)/rcfdemSolverRhoSteadyPimple diff --git a/applications/solvers/cfdemSolverRhoSimple/Make/options b/applications/solvers/rcfdemSolverRhoSteadyPimple/Make/options similarity index 93% rename from applications/solvers/cfdemSolverRhoSimple/Make/options rename to applications/solvers/rcfdemSolverRhoSteadyPimple/Make/options index 0377ece5..b2b37fe7 100644 --- a/applications/solvers/cfdemSolverRhoSimple/Make/options +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/Make/options @@ -15,9 +15,11 @@ EXE_INC = \ -I$(LIB_SRC)/sampling/lnInclude \ -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \ -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \ + -I$(CFDEM_SRC_DIR)/recurrence/lnInclude \ EXE_LIBS = \ -L$(CFDEM_LIB_DIR)\ + -lrecurrence \ -lcompressibleTransportModels \ -lfluidThermophysicalModels \ -lspecie \ diff --git a/applications/solvers/cfdemSolverRhoSimple/UEqn.H b/applications/solvers/rcfdemSolverRhoSteadyPimple/UEqn.H similarity index 64% rename from applications/solvers/cfdemSolverRhoSimple/UEqn.H rename to applications/solvers/rcfdemSolverRhoSteadyPimple/UEqn.H index 8fbd30f2..9e75193e 100644 --- a/applications/solvers/cfdemSolverRhoSimple/UEqn.H +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/UEqn.H @@ -4,7 +4,7 @@ particleCloud.otherForces(fOther); tmp tUEqn ( fvm::div(phi, U) - + particleCloud.divVoidfractionTau(U, voidfraction) + + particleCloud.divVoidfractionTau(U, voidfractionRec) + fvm::Sp(Ksl,U) - fOther == @@ -18,13 +18,16 @@ fvOptions.constrain(UEqn); if (modelType=="B" || modelType=="Bfull") { - solve(UEqn == -fvc::grad(p)+ Ksl*Us); + solve(UEqn == -fvc::grad(p)+ Ksl*UsRec); } else { - solve(UEqn == -voidfraction*fvc::grad(p)+ Ksl*Us); + solve(UEqn == -voidfractionRec*fvc::grad(p)+ Ksl*UsRec); } +//U.relax(); +#include "limitU.H" + fvOptions.correct(U); K = 0.5*magSqr(U); diff --git a/applications/solvers/cfdemSolverRhoSimple/createFieldRefs.H b/applications/solvers/rcfdemSolverRhoSteadyPimple/createFieldRefs.H similarity index 100% rename from applications/solvers/cfdemSolverRhoSimple/createFieldRefs.H rename to applications/solvers/rcfdemSolverRhoSteadyPimple/createFieldRefs.H diff --git a/applications/solvers/cfdemSolverRhoSimple/createFields.H b/applications/solvers/rcfdemSolverRhoSteadyPimple/createFields.H similarity index 76% rename from applications/solvers/cfdemSolverRhoSimple/createFields.H rename to applications/solvers/rcfdemSolverRhoSteadyPimple/createFields.H index a9225229..454911d9 100644 --- a/applications/solvers/cfdemSolverRhoSimple/createFields.H +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/createFields.H @@ -51,6 +51,19 @@ Info<< "Reading thermophysical properties\n" << endl; mesh ); + volScalarField voidfractionRec + ( + IOobject + ( + "voidfractionRec", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + voidfraction + ); + volScalarField addSource ( IOobject @@ -58,10 +71,11 @@ Info<< "Reading thermophysical properties\n" << endl; "addSource", runTime.timeName(), mesh, - IOobject::MUST_READ, + IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), - mesh + mesh, + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) ); Info<< "\nCreating fluid-particle heat flux field\n" << endl; @@ -102,11 +116,12 @@ Info<< "Reading thermophysical properties\n" << endl; "thCond", runTime.timeName(), mesh, - IOobject::NO_READ, + IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), mesh, - dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0) + dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0), + "zeroGradient" ); Info<< "\nCreating heat capacity field\n" << endl; @@ -158,7 +173,7 @@ Info<< "Reading thermophysical properties\n" << endl; dimensionedScalar::lookupOrDefault ( "rhoMax", - simple.dict(), + pimple.dict(), dimDensity, GREAT ) @@ -169,12 +184,45 @@ Info<< "Reading thermophysical properties\n" << endl; dimensionedScalar::lookupOrDefault ( "rhoMin", - simple.dict(), + pimple.dict(), dimDensity, 0 ) ); + dimensionedScalar pMax + ( + dimensionedScalar::lookupOrDefault + ( + "pMax", + pimple.dict(), + dimPressure, + GREAT + ) + ); + + dimensionedScalar pMin + ( + dimensionedScalar::lookupOrDefault + ( + "pMin", + pimple.dict(), + dimPressure, + -GREAT + ) + ); + + dimensionedScalar UMax + ( + dimensionedScalar::lookupOrDefault + ( + "UMax", + pimple.dict(), + dimVelocity, + -1.0 + ) + ); + Info<< "Creating turbulence model\n" << endl; autoPtr turbulence ( @@ -189,7 +237,7 @@ Info<< "Reading thermophysical properties\n" << endl; label pRefCell = 0; scalar pRefValue = 0.0; - setRefCell(p, simple.dict(), pRefCell, pRefValue); + setRefCell(p, pimple.dict(), pRefCell, pRefValue); mesh.setFluxRequired(p.name()); @@ -217,11 +265,11 @@ Info<< "Reading thermophysical properties\n" << endl; "Ksl", runTime.timeName(), mesh, - IOobject::MUST_READ, + IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE ), - mesh - //dimensionedScalar("0", dimensionSet(1, -3, -1, 0, 0), 1.0) + mesh, + dimensionedScalar("0", dimensionSet(1, -3, -1, 0, 0), 0.0) ); @@ -239,4 +287,20 @@ Info<< "Reading thermophysical properties\n" << endl; mesh ); + volVectorField UsRec + ( + IOobject + ( + "UsRec", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + Us + ); + + + dimensionedScalar kf("0", dimensionSet(1, 1, -3, -1, 0, 0, 0), 0.026); + //=============================== diff --git a/applications/solvers/rcfdemSolverRhoSteadyPimple/limitP.H b/applications/solvers/rcfdemSolverRhoSteadyPimple/limitP.H new file mode 100644 index 00000000..f0971a14 --- /dev/null +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/limitP.H @@ -0,0 +1,2 @@ +p = max(p, pMin); +p = min(p, pMax); diff --git a/applications/solvers/rcfdemSolverRhoSteadyPimple/limitU.H b/applications/solvers/rcfdemSolverRhoSteadyPimple/limitU.H new file mode 100644 index 00000000..f699b25c --- /dev/null +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/limitU.H @@ -0,0 +1,11 @@ +if (UMax.value() > 0) +{ + forAll(U,cellI) + { + scalar mU(mag(U[cellI])); + if (mU > UMax.value()) + { + U[cellI] *= UMax.value() / mU; + } + } +} diff --git a/applications/solvers/cfdemSolverRhoSimple/pEqn.H b/applications/solvers/rcfdemSolverRhoSteadyPimple/pEqn.H similarity index 80% rename from applications/solvers/cfdemSolverRhoSimple/pEqn.H rename to applications/solvers/rcfdemSolverRhoSteadyPimple/pEqn.H index ed546344..f40c57a8 100644 --- a/applications/solvers/cfdemSolverRhoSimple/pEqn.H +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/pEqn.H @@ -7,14 +7,15 @@ volScalarField rAU(1.0/UEqn.A()); surfaceScalarField rhorAUf("rhorAUf", fvc::interpolate(rhoeps*rAU)); if (modelType=="A") { - rhorAUf *= fvc::interpolate(voidfraction); + rhorAUf *= fvc::interpolate(voidfractionRec); } volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p)); +//tUEqn.clear(); -surfaceScalarField phiUs("phiUs", fvc::interpolate(rhoeps*rAU*Ksl*Us)& mesh.Sf()); +surfaceScalarField phiUs("phiUs", fvc::interpolate(rhoeps*rAU*Ksl*UsRec)& mesh.Sf()); -if (simple.transonic()) +if (pimple.transonic()) { // transonic version not implemented yet } @@ -34,7 +35,7 @@ else // Update the pressure BCs to ensure flux consistency constrainPressure(p, rhoeps, U, phi, rhorAUf); - while (simple.correctNonOrthogonal()) + while (pimple.correctNonOrthogonal()) { // Pressure corrector fvScalarMatrix pEqn @@ -49,7 +50,7 @@ else pEqn.solve(); - if (simple.finalNonOrthogonalIter()) + if (pimple.finalNonOrthogonalIter()) { phi += pEqn.flux(); } @@ -59,6 +60,8 @@ else // Explicitly relax pressure for momentum corrector p.relax(); +#include "limitP.H" + // Recalculate density from the relaxed pressure rho = thermo.rho(); rho = max(rho, rhoMin); @@ -69,13 +72,15 @@ Info<< "rho max/min : " << max(rho).value() if (modelType=="A") { - U = HbyA - rAU*(voidfraction*fvc::grad(p)-Ksl*Us); + U = HbyA - rAU*(voidfractionRec*fvc::grad(p)-Ksl*UsRec); } else { - U = HbyA - rAU*(fvc::grad(p)-Ksl*Us); + U = HbyA - rAU*(fvc::grad(p)-Ksl*UsRec); } +#include "limitU.H" + U.correctBoundaryConditions(); fvOptions.correct(U); K = 0.5*magSqr(U); diff --git a/applications/solvers/cfdemSolverRhoSimple/cfdemSolverRhoSimple.C b/applications/solvers/rcfdemSolverRhoSteadyPimple/rcfdemSolverRhoSteadyPimple.C similarity index 55% rename from applications/solvers/cfdemSolverRhoSimple/cfdemSolverRhoSimple.C rename to applications/solvers/rcfdemSolverRhoSteadyPimple/rcfdemSolverRhoSteadyPimple.C index 10518925..6c39a428 100644 --- a/applications/solvers/cfdemSolverRhoSimple/cfdemSolverRhoSimple.C +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/rcfdemSolverRhoSteadyPimple.C @@ -17,23 +17,31 @@ License Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria Application - cfdemSolverRhoSimple + rcfdemSolverRhoSteadyPimple Description - Steady-state solver for turbulent flow of compressible fluids based on - rhoSimpleFoam where functionality for CFD-DEM coupling has been added. - + Transient (DEM) + steady-state (CFD) solver for compressible flow using the + flexible PIMPLE (PISO-SIMPLE) algorithm. Particle-motion is obtained from + a recurrence process. + Turbulence modelling is generic, i.e. laminar, RAS or LES may be selected. + The code is an evolution of the solver rhoPimpleFoam in OpenFOAM(R) 4.x, + where additional functionality for CFD-DEM coupling is added. \*---------------------------------------------------------------------------*/ #include "fvCFD.H" #include "psiThermo.H" #include "turbulentFluidThermoModel.H" #include "bound.H" -#include "simpleControl.H" +#include "pimpleControl.H" #include "fvOptions.H" #include "localEulerDdtScheme.H" #include "fvcSmooth.H" +#include "cfdemCloudRec.H" +#include "recBase.H" +#include "recModel.H" +#include "recPath.H" + #include "cfdemCloudEnergy.H" #include "implicitCouple.H" #include "clockModel.H" @@ -60,18 +68,37 @@ int main(int argc, char *argv[]) #include "createFvOptions.H" // create cfdemCloud - #include "readGravitationalAcceleration.H" - cfdemCloudEnergy particleCloud(mesh); + //#include "readGravitationalAcceleration.H" + cfdemCloudRec particleCloud(mesh); #include "checkModelType.H" + recBase recurrenceBase(mesh); + #include "updateFields.H" turbulence->validate(); + //#include "compressibleCourantNo.H" + //#include "setInitialDeltaT.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + label recTimeIndex = 0; + scalar recTimeStep = recurrenceBase.recM().recTimeStep(); + scalar startTime = runTime.startTime().value(); + + const IOdictionary& couplingProps = particleCloud.couplingProperties(); + label nEveryFlow(couplingProps.lookupOrDefault("nEveryFlow",1)); + Info << "Solving flow equations every " << nEveryFlow << " steps.\n" << endl; + label stepcounter = 0; + Info<< "\nStarting time loop\n" << endl; - while (simple.loop(runTime)) + while (runTime.run()) { + #include "readTimeControls.H" + #include "compressibleCourantNo.H" + #include "setDeltaT.H" + + runTime++; + particleCloud.clockM().start(1,"Global"); Info<< "Time = " << runTime.timeName() << nl << endl; @@ -80,6 +107,9 @@ int main(int argc, char *argv[]) particleCloud.clockM().start(2,"Coupling"); bool hasEvolved = particleCloud.evolve(voidfraction,Us,U); + //voidfraction = voidfractionRec; + //Us = UsRec; + if(hasEvolved) { particleCloud.smoothingM().smoothen(particleCloud.forceM(0).impParticleForces()); @@ -100,25 +130,52 @@ int main(int argc, char *argv[]) particleCloud.clockM().stop("Coupling"); particleCloud.clockM().start(26,"Flow"); + volScalarField rhoeps("rhoeps",rho*voidfractionRec); + if (stepcounter%nEveryFlow==0) + { + while (pimple.loop()) + { + // if needed, perform drag update here + if (pimple.nCorrPIMPLE() <= 1) + { + #include "rhoEqn.H" + } - volScalarField rhoeps("rhoeps",rho*voidfraction); - // Pressure-velocity SIMPLE corrector + // --- Pressure-velocity PIMPLE corrector loop - #include "UEqn.H" + #include "UEqn.H" + #include "EEqn.H" + // --- Pressure corrector loop + while (pimple.correct()) + { + // besides this pEqn, OF offers a "pimple consistent"-option + #include "pEqn.H" + rhoeps=rho*voidfractionRec; + } - // besides this pEqn, OF offers a "simple consistent"-option - #include "pEqn.H" - rhoeps=rho*voidfraction; + if (pimple.turbCorr()) + { + turbulence->correct(); + } + } + } + stepcounter++; + particleCloud.clockM().stop("Flow"); - #include "EEqn.H" - - turbulence->correct(); - - particleCloud.clockM().start(32,"postFlow"); - if(hasEvolved) particleCloud.postFlow(); + particleCloud.clockM().start(31,"postFlow"); + particleCloud.postFlow(); particleCloud.clockM().stop("postFlow"); + particleCloud.clockM().start(32,"ReadFields"); + if ( runTime.timeOutputValue() - startTime - (recTimeIndex+1)*recTimeStep + 1.0e-5 > 0.0 ) + { + recurrenceBase.updateRecFields(); + #include "updateFields.H" + recTimeIndex++; + } + particleCloud.clockM().stop("ReadFields"); + runTime.write(); @@ -126,7 +183,7 @@ int main(int argc, char *argv[]) << " ClockTime = " << runTime.elapsedClockTime() << " s" << nl << endl; - particleCloud.clockM().stop("Flow"); + particleCloud.clockM().stop("Global"); } diff --git a/applications/solvers/rcfdemSolverRhoSteadyPimple/updateFields.H b/applications/solvers/rcfdemSolverRhoSteadyPimple/updateFields.H new file mode 100644 index 00000000..182cbf78 --- /dev/null +++ b/applications/solvers/rcfdemSolverRhoSteadyPimple/updateFields.H @@ -0,0 +1,8 @@ +// is it neccessary to extend recurrence path? +if(recurrenceBase.recM().endOfPath()) +{ + recurrenceBase.extendPath(); +} + +recurrenceBase.recM().exportVolScalarField("voidfraction",voidfractionRec); +recurrenceBase.recM().exportVolVectorField("Us",UsRec); diff --git a/applications/solvers/recSolverTurbTransport/Make/files b/applications/solvers/recSolverTurbTransport/Make/files new file mode 100755 index 00000000..c984de5c --- /dev/null +++ b/applications/solvers/recSolverTurbTransport/Make/files @@ -0,0 +1,3 @@ +recSolverTurbTransport.C + +EXE=$(CFDEM_APP_DIR)/recSolverTurbTransport diff --git a/applications/solvers/recSolverTurbTransport/Make/options b/applications/solvers/recSolverTurbTransport/Make/options new file mode 100755 index 00000000..686f676c --- /dev/null +++ b/applications/solvers/recSolverTurbTransport/Make/options @@ -0,0 +1,27 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + +EXE_INC = \ + -I$(CFDEM_OFVERSION_DIR) \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \ + -I$(LIB_SRC)/transportModels \ + -I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \ + -I$(CFDEM_SRC_DIR)/recurrence/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/derived/cfdemCloudRec \ + +EXE_LIBS = \ + -L$(CFDEM_LIB_DIR)\ + -lrecurrence \ + -lturbulenceModels \ + -lincompressibleTurbulenceModels \ + -lincompressibleTransportModels \ + -lfiniteVolume \ + -lmeshTools \ + -lfvOptions \ + -l$(CFDEM_LIB_NAME) \ + $(CFDEM_ADD_LIB_PATHS) \ + $(CFDEM_ADD_LIBS) diff --git a/applications/solvers/recSolverTurbTransport/TEq.H b/applications/solvers/recSolverTurbTransport/TEq.H new file mode 100755 index 00000000..e28a172d --- /dev/null +++ b/applications/solvers/recSolverTurbTransport/TEq.H @@ -0,0 +1,17 @@ + +volScalarField alphaEff("alphaEff", turbulence->nu()/Sc + dU2/Sct); + +TEqn = +( + fvm::ddt(T) + + fvm::div(phiRec, T) + - fvm::laplacian(alphaEff, T) + == + fvOptions(T) +); + +TEqn.relax(relaxCoeff); + +fvOptions.constrain(TEqn); + +TEqn.solve(); diff --git a/applications/solvers/recSolverTurbTransport/createFields.H b/applications/solvers/recSolverTurbTransport/createFields.H new file mode 100755 index 00000000..3b9b3af1 --- /dev/null +++ b/applications/solvers/recSolverTurbTransport/createFields.H @@ -0,0 +1,174 @@ + // dummy fields + Info<< "\nCreating dummy pressure and density fields\n" << endl; + volScalarField p + ( + IOobject + ( + "p", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh, + dimensionedScalar("p", dimensionSet(1, 2, -2, 0, 0), 1.0) + ); + + volScalarField rho + ( + IOobject + ( + "rho", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh, + dimensionedScalar("rho", dimensionSet(1, -3, 0, 0, 0), 1.0) + ); + + // recurrence fields + Info<< "\nCreating recurrence fields.\n" << endl; + + volVectorField URec + ( + IOobject + ( + "URec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + volScalarField U2Rec + ( + IOobject + ( + "U2Rec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + // calculated fields + Info<< "\nCreating fields subject to calculation\n" << endl; + + volScalarField delta + ( + IOobject + ( + "delta", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedScalar("delta", dimLength, 0.0) + ); + + delta.primitiveFieldRef()=pow(mesh.V(),1.0/3.0); + delta.write(); + + + Info<< "\ncreating dU2\n" << endl; + + volScalarField dU2 + ( + IOobject + ( + "dU2", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + sqrt(0.5*mag(U2Rec - magSqr(URec)))*delta*0.094 + ); + + forAll(dU2, cellI) + { + if (U2Rec[cellI]-magSqr(URec[cellI]) < 0.0) + { + dU2[cellI] = 0.0; + } + } + + dU2.write(); + +Info<< "Calculating face flux field phiRec\n" << endl; +surfaceScalarField phiRec + ( + IOobject + ( + "phiRec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + linearInterpolate(URec) & mesh.Sf() + ); + + phiRec.write(); + + singlePhaseTransportModel laminarTransport(URec, phiRec); + + autoPtr turbulence + ( + incompressible::turbulenceModel::New(URec, phiRec, laminarTransport) + ); + + dimensionedScalar Sc("Sc", dimless, laminarTransport); + dimensionedScalar Sct("Sct", dimless, laminarTransport); + + // create concentration field + Info<< "Creating scalar transport field\n" << endl; + + volScalarField T + ( + IOobject + ( + "T", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + fvScalarMatrix TEqn(T, dimless*dimVolume/(dimTime)); + + scalar relaxCoeff(0.0); + + Info<< "reading clockProperties\n" << endl; + + IOdictionary clockProperties + ( + IOobject + ( + "clockProperties", + mesh.time().constant(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ); + + autoPtr myClock + ( + clockModel::New + ( + clockProperties, + mesh.time() + ) + ); + diff --git a/applications/solvers/recSolverTurbTransport/readFields.H b/applications/solvers/recSolverTurbTransport/readFields.H new file mode 100755 index 00000000..13dad011 --- /dev/null +++ b/applications/solvers/recSolverTurbTransport/readFields.H @@ -0,0 +1,14 @@ + +recurrenceBase.recM().exportVolScalarField("U2Mean",U2Rec); +recurrenceBase.recM().exportVolVectorField("UMean",URec); +phiRec=linearInterpolate(URec) & mesh.Sf(); + +dU2=sqrt(0.5*mag(U2Rec - magSqr(URec)))*delta*0.094; + +forAll(dU2, cellI) +{ + if (U2Rec[cellI]-magSqr(URec[cellI]) < 0.0) + { + dU2[cellI] = 0.0; + } +} diff --git a/applications/solvers/recSolverTurbTransport/recSolverTurbTransport.C b/applications/solvers/recSolverTurbTransport/recSolverTurbTransport.C new file mode 100755 index 00000000..e104b1b6 --- /dev/null +++ b/applications/solvers/recSolverTurbTransport/recSolverTurbTransport.C @@ -0,0 +1,113 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger, Gerhard Holzinger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . + +Application + Turbulent Transport Solver Recurrence + +Description + Solves a transport equation for a passive scalar on a single-phase solution + for a solver based on recurrence statistics + +Rules + Solution data to compute the recurrence statistics from, needs to + reside in $CASE_ROOT/dataBase + Time step data in dataBase needs to be evenly spaced in time + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" +#include "singlePhaseTransportModel.H" +#include "turbulentTransportModel.H" +#include "fvOptions.H" + +#include "recBase.H" +#include "recModel.H" + +#include "clockModel.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + #include "postProcess.H" + #include "setRootCase.H" + #include "createTime.H" + #include "createMesh.H" + #include "createControl.H" + #include "createFields.H" + #include "createFvOptions.H" + + recBase recurrenceBase(mesh); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info<< "\nCalculating particle trajectories based on recurrence statistics\n" << endl; + + label recTimeIndex(0); + scalar recTimeStep_=recurrenceBase.recM().recTimeStep(); + + while (runTime.run()) + { + + myClock().start(1,"Global"); + + runTime++; + + Info<< "Time = " << runTime.timeName() << nl << endl; + + myClock().start(2,"fieldUpdate"); + + if ( runTime.timeOutputValue() - (recTimeIndex+1)*recTimeStep_ + 1.0e-5 > 0.0 ) + { + Info << "Updating fields at run time " << runTime.timeOutputValue() + << " corresponding to recurrence time " << (recTimeIndex+1)*recTimeStep_ << ".\n" << endl; + recurrenceBase.updateRecFields(); + #include "readFields.H" + recTimeIndex++; + } + + myClock().stop("fieldUpdate"); + + myClock().start(3,"speciesEqn"); + #include "TEq.H" + myClock().stop("speciesEqn"); + + runTime.write(); + + Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" + << " ClockTime = " << runTime.elapsedClockTime() << " s" + << nl << endl; + + myClock().stop("Global"); + + } + + myClock().evalPar(); + myClock().normHist(); + + Info<< "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/solvers/rtfmSolverSpecies/Make/files b/applications/solvers/rtfmSolverSpecies/Make/files new file mode 100644 index 00000000..263345a8 --- /dev/null +++ b/applications/solvers/rtfmSolverSpecies/Make/files @@ -0,0 +1,3 @@ +rtfmSolverSpecies.C + +EXE=$(CFDEM_APP_DIR)/rtfmSolverSpecies diff --git a/applications/solvers/rtfmSolverSpecies/Make/options b/applications/solvers/rtfmSolverSpecies/Make/options new file mode 100644 index 00000000..9443c2f8 --- /dev/null +++ b/applications/solvers/rtfmSolverSpecies/Make/options @@ -0,0 +1,27 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + +EXE_INC = \ + -I$(CFDEM_OFVERSION_DIR) \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \ + -I$(LIB_SRC)/transportModels \ + -I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \ + -I$(CFDEM_SRC_DIR)/recurrence/lnInclude \ + -I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/derived/cfdemCloudRec \ + +EXE_LIBS = \ + -L$(CFDEM_LIB_DIR)\ + -lrecurrence \ + -lturbulenceModels \ + -lincompressibleTurbulenceModels \ + -lincompressibleTransportModels \ + -lfiniteVolume \ + -lmeshTools \ + -lfvOptions \ + -l$(CFDEM_LIB_NAME) \ + $(CFDEM_ADD_LIB_PATHS) \ +$(CFDEM_ADD_LIBS) diff --git a/applications/solvers/rtfmSolverSpecies/TEq.H b/applications/solvers/rtfmSolverSpecies/TEq.H new file mode 100644 index 00000000..082f23cf --- /dev/null +++ b/applications/solvers/rtfmSolverSpecies/TEq.H @@ -0,0 +1,14 @@ + TEqn = + ( + fvm::ddt(alpha2Rec, T) + + fvm::div(phi2Rec, T) + - fvm::laplacian(alpha2Rec*turbulence->nu(), T) + == + fvOptions(alpha2Rec, T) // no fvOptions support yet + ); + + TEqn.relax(relaxCoeff); + + fvOptions.constrain(TEqn); // no fvOptions support yet + + TEqn.solve(); diff --git a/applications/solvers/rtfmSolverSpecies/createFields.H b/applications/solvers/rtfmSolverSpecies/createFields.H new file mode 100644 index 00000000..ec395754 --- /dev/null +++ b/applications/solvers/rtfmSolverSpecies/createFields.H @@ -0,0 +1,135 @@ + // dummy fields + Info << "\nCreating dummy pressure and density fields\n" << endl; + volScalarField p + ( + IOobject + ( + "p", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh, + dimensionedScalar("p", dimensionSet(1, 2, -2, 0, 0), 1.0) + ); + + volScalarField rho + ( + IOobject + ( + "rho", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh, + dimensionedScalar("rho", dimensionSet(1, -3, 0, 0, 0), 1.0) + ); + + // recurrence fields + Info << "\nCreating recurrence fields.\n" << endl; + volVectorField U1Rec + ( + IOobject + ( + "U1Rec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + volScalarField alpha1Rec + ( + IOobject + ( + "alpha1Rec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + volVectorField U2Rec + ( + IOobject + ( + "U2Rec", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + // calculated fields + Info << "\nCreating fields subject to calculation\n" << endl; + volScalarField alpha2Rec + ( + IOobject + ( + "alpha2Rec", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + 1-alpha1Rec + ); + + + // write fields for t=t_start + alpha2Rec.write(); +//=============================== + + + Info << "Calculating face flux field phi\n" << endl; + surfaceScalarField phi2Rec + ( + IOobject + ( + "phi2Rec", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + linearInterpolate(U2Rec*alpha2Rec) & mesh.Sf() + ); + phi2Rec.write(); + + singlePhaseTransportModel laminarTransport(U2Rec, phi2Rec); + + autoPtr turbulence + ( + incompressible::turbulenceModel::New(U2Rec, phi2Rec, laminarTransport) + ); + + // transport stuff + + // create concentration field + volScalarField T + ( + IOobject + ( + "T", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh + ); + + fvScalarMatrix TEqn(T, dimless*dimVolume/(dimTime)); + + T.write(); + + scalar relaxCoeff(0.0); diff --git a/applications/solvers/rtfmSolverSpecies/readFields.H b/applications/solvers/rtfmSolverSpecies/readFields.H new file mode 100644 index 00000000..303782b2 --- /dev/null +++ b/applications/solvers/rtfmSolverSpecies/readFields.H @@ -0,0 +1,6 @@ +recurrenceBase.recM().exportVolScalarField("alpha.air",alpha1Rec); +alpha2Rec=1-alpha1Rec; +recurrenceBase.recM().exportVolVectorField("U.air",U1Rec); +recurrenceBase.recM().exportVolVectorField("U.water",U2Rec); +recurrenceBase.recM().exportSurfaceScalarField("phi.water",phi2Rec); + diff --git a/applications/solvers/rtfmSolverSpecies/rtfmSolverSpecies.C b/applications/solvers/rtfmSolverSpecies/rtfmSolverSpecies.C new file mode 100644 index 00000000..db1250b8 --- /dev/null +++ b/applications/solvers/rtfmSolverSpecies/rtfmSolverSpecies.C @@ -0,0 +1,112 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger, Gerhard Holzinger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . + +Application + cfdemSolverRecurrence + +Description + Solves a transport equation for a passive scalar on a two-phase solution + Test-bed for a solver based on recurrence statistics + +Rules + Solution data to compute the recurrence statistics from, needs to + reside in $CASE_ROOT/dataBase + Time step data in dataBase needs to be evenly spaced in time + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" +#include "singlePhaseTransportModel.H" +#include "turbulentTransportModel.H" +#include "fvOptions.H" + +#include "cfdemCloudRec.H" +#include "recBase.H" +#include "recModel.H" + +#include "cfdemCloud.H" +#include "clockModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + #include "postProcess.H" + #include "setRootCase.H" + #include "createTime.H" + #include "createMesh.H" + #include "createControl.H" + #include "createFields.H" + #include "createFvOptions.H" + + cfdemCloudRec particleCloud(mesh); + recBase recurrenceBase(mesh); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info << "\nCalculating particle trajectories based on recurrence statistics\n" << endl; + + label recTimeIndex(0); + scalar recTimeStep_=recurrenceBase.recM().recTimeStep(); + + while (runTime.run()) + { + runTime++; + + // do stuff (every lagrangian time step) + particleCloud.clockM().start(1,"Global"); + + Info << "Time = " << runTime.timeName() << nl << endl; + + particleCloud.clockM().start(2,"Flow"); + #include "TEq.H" + particleCloud.clockM().stop("Flow"); + + + if ( runTime.timeOutputValue() - (recTimeIndex+1)*recTimeStep_ + 1.0e-5 > 0.0 ) + { + Info << "Updating fields at run time " << runTime.timeOutputValue() + << " corresponding to recurrence time " << (recTimeIndex+1)*recTimeStep_ << ".\n" << endl; + recurrenceBase.updateRecFields(); + #include "readFields.H" + recTimeIndex++; + } + + particleCloud.clockM().start(27,"Output"); + runTime.write(); + particleCloud.clockM().stop("Output"); + + particleCloud.clockM().stop("Global"); + + Info << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" + << " ClockTime = " << runTime.elapsedClockTime() << " s" + << nl << endl; + } + + Info << "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/Allwclean b/applications/solvers/testTwoFluidRecurrenceTurbulence/Allwclean new file mode 100755 index 00000000..569edc66 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/Allwclean @@ -0,0 +1,9 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +set -x + +wclean libso recurrenceTurbulence + +wclean + +# ----------------------------------------------------------------- end-of-file diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/Allwmake b/applications/solvers/testTwoFluidRecurrenceTurbulence/Allwmake new file mode 100755 index 00000000..6bff4cfb --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/Allwmake @@ -0,0 +1,9 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +set -x + +wmake libso recurrenceTurbulence + +wmake + +# ----------------------------------------------------------------- end-of-file diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/CEqn.H b/applications/solvers/testTwoFluidRecurrenceTurbulence/CEqn.H new file mode 100644 index 00000000..7998edc1 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/CEqn.H @@ -0,0 +1,29 @@ +// build equation system +/* + Note the use of the effective viscosity, which is provided by the turbulence model + The recurrence-based turbulence models are derived from the standard base classes + of OpenFOAM, thus they behave as a normal turbulence model would. +*/ + +alphaRhoPhiCarrier = linearInterpolate(alpha2*rhoCarrier)*phi2; + +fvScalarMatrix CEqn +( + fvm::ddt(alphaCarrier*rhoCarrier, C) + + fvm::div(alphaRhoPhiCarrier, C, "div(alphaRhoPhi,C)") + - fvm::Sp(fvc::div(alphaRhoPhiCarrier), C) + + - fvm::laplacian + ( + fvc::interpolate(alpha2) + *fvc::interpolate(carrierPhase.turbulence().muEff()/Sc), + C + ) + == + fvm::SuSp(alphaCarrier*(1.0 - alphaCarrier)*rhoCarrier*K, C) + + fvOptions(alphaCarrier*rhoCarrier, C) +); + +// solve equations +fvOptions.constrain(CEqn); +CEqn.solve(); diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/Make/files b/applications/solvers/testTwoFluidRecurrenceTurbulence/Make/files new file mode 100644 index 00000000..37b9ed4a --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/Make/files @@ -0,0 +1,3 @@ +testTwoFluidRecurrenceTurbulence.C + +EXE = $(FOAM_USER_APPBIN)/testTwoFluidRecurrenceTurbulence diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/Make/options b/applications/solvers/testTwoFluidRecurrenceTurbulence/Make/options new file mode 100644 index 00000000..64f0b98d --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/Make/options @@ -0,0 +1,31 @@ +EXE_INC = \ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/reactingTwoPhaseEulerFoam \ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/reactingTwoPhaseEulerFoam/twoPhaseSystem/lnInclude \ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/phaseSystems/lnInclude \ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/interfacialModels/lnInclude \ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/interfacialCompositionModels/lnInclude \ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/twoPhaseCompressibleTurbulenceModels/lnInclude \ + -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \ + -I$(LIB_SRC)/transportModels/compressible/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/phaseCompressible/lnInclude \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/sampling/lnInclude \ + -I../../../src/recurrence/lnInclude \ + -IrecurrenceTurbulence/lnInclude + +EXE_LIBS = \ + -lreactingPhaseSystem \ + -lreactingTwoPhaseSystem \ + -lreactingEulerianInterfacialModels \ + -lreactingEulerianInterfacialCompositionModels \ + -ltwoPhaseReactingTurbulenceModels \ + -lfiniteVolume \ + -lfvOptions \ + -lmeshTools \ + -lsampling \ + -L$(FOAM_USER_LIBBIN) \ + -lrecurrence \ + -lrecurrenceTwoPhaseTurbulenceModels diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/checkTurbulenceModels.H b/applications/solvers/testTwoFluidRecurrenceTurbulence/checkTurbulenceModels.H new file mode 100644 index 00000000..09e72bf8 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/checkTurbulenceModels.H @@ -0,0 +1,70 @@ +//=============================== +// recurrence turbulence +//=============================== + + + // check both phases for turbulence models + forAllIter(PtrListDictionary, fluid.phases(), iter) + { + phaseModel& phase = iter(); + + Info << "Checking phase " << phase.name() << "'s turbulence model: " + << phase.turbulence().type() << endl; + + /* + Check for laminar turbulence. This works with OpenFOAM-4.0 and OpenFOAM-5.0, + as the laminar, multi-phase turbulence model is named "laminar" in OF-4.0 + and "Stokes" in OF-5.0 + */ + if (phase.turbulence().type() == "laminar" || phase.turbulence().type() == "Stokes") + { + // do nothing + } + else if (isA(phase.turbulence())) + { + /* + create a reference of the type recurrenceTurbulenceModel + register the recurrence model with the recurrenceTurbulenceModel + */ + + // get const-reference to the turbulence model + const phaseCompressibleTurbulenceModel& turbConstRef = phase.turbulence(); + + // cast away const-ness, the underlying turbulence model is not a const object, so this is bad but fine + phaseCompressibleTurbulenceModel& turbRef = const_cast(turbConstRef); + + // cast away the wrapper class, to get a reference to the turbulence models' base class + PhaseCompressibleTurbulenceModel& baseTurbRef + ( + static_cast&>(turbRef) + ); + + // casting down the family tree + Foam::recurrenceTurbulenceModel& recTurbRef + ( + dynamic_cast(baseTurbRef) + ); + + + // set recurrenceBase pointer + recTurbRef.setRecurrenceBasePtr(&recurrenceBase); + + + // check model settings + turbRef.validate(); + } + else + { + /* + In a recurrence run, we do not compute any turbulence as we do not solve the fluid flow + At this point, the phase is not laminar (i.e. not using turbulence) or + using recurrenceTurbulence (i.e. taking turbulent quantities from the data base). + Hence, abort! + */ + FatalError + << "Wrong turbulence model type " + << phase.turbulence().type() << " for phase " << phase.name() << nl << nl + << "Valid turbulence model types are types derived from recurrenceTurbulenceModel or laminar" << endl + << exit(FatalError); + } + } diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/createTransportFields.H b/applications/solvers/testTwoFluidRecurrenceTurbulence/createTransportFields.H new file mode 100644 index 00000000..75aaf6bb --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/createTransportFields.H @@ -0,0 +1,79 @@ +/* --------------------------------------------------------------------------------- */ +/* read flotation properties */ +/* --------------------------------------------------------------------------------- */ + +Info<< "Reading scalarTransportProperties\n" << endl; +IOdictionary scalarTransportProperties +( + IOobject + ( + "scalarTransportProperties", + runTime.constant(), + mesh, + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE + ) +); + + +const scalar Sc(scalarTransportProperties.lookupOrDefault("Sc",scalar(1.0))); + + +const word carrierPhaseName(scalarTransportProperties.lookup("carrierPhase")); + +if (carrierPhaseName != phase1.name() && carrierPhaseName != phase2.name()) +{ + FatalError << "No valid carrier phase specified" << nl + << "Valid phase names are: " << nl + << phase1.name() << ", " << phase2.name() + << abort(FatalError); +} + +phaseModel& carrierPhase = (carrierPhaseName == phase1.name()) ? phase1 : phase2; + +const word dispersePhaseName = (carrierPhaseName == phase1.name()) ? phase2.name() : phase1.name(); + + +volScalarField& rhoCarrier = carrierPhase.thermo().rho(); +volScalarField& alphaCarrier = carrierPhase; +surfaceScalarField& alphaRhoPhiCarrier = carrierPhase.alphaRhoPhi(); + + +volScalarField contErrCarrier +( + "contErrCarrier", + fvc::ddt(alphaCarrier, rhoCarrier) +); + + + +Info<< "Reading field C\n" << endl; +volScalarField C +( + IOobject + ( + "C", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE + ), + mesh +); + +volScalarField K +( + IOobject + ( + "K", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ), + mesh +); + + + + diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/readFields.H b/applications/solvers/testTwoFluidRecurrenceTurbulence/readFields.H new file mode 100644 index 00000000..d07d3a5a --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/readFields.H @@ -0,0 +1,9 @@ +// update flow fields +recurrenceBase.recM().exportVolScalarField("alpha."+carrierPhaseName,alpha2); +recurrenceBase.recM().exportVolScalarField("alpha."+dispersePhaseName,alpha1); + +recurrenceBase.recM().exportVolVectorField("U."+carrierPhaseName,U2); + +// update turbulence models +phase1.correctTurbulence(); +phase2.correctTurbulence(); diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Allwclean b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Allwclean new file mode 100755 index 00000000..dcb9731a --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Allwclean @@ -0,0 +1,7 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + + +wclean libso + +#------------------------------------------------------------------------------ diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Allwmake b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Allwmake new file mode 100755 index 00000000..2471b6d5 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Allwmake @@ -0,0 +1,9 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +# Parse arguments for library compilation +. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments + +wmake $targetType + +#------------------------------------------------------------------------------ diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Make/files b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Make/files new file mode 100644 index 00000000..3e754a88 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Make/files @@ -0,0 +1,10 @@ +recurrenceTurbulenceModel/recurrenceTurbulenceModel.C + + +recurrenceTurbulenceModels.C + +recurrenceKEpsilon/recurrenceKEpsilon.C +recurrenceKOmega/recurrenceKOmega.C +recurrenceSmagorinsky/recurrenceSmagorinsky.C + +LIB = $(FOAM_USER_LIBBIN)/librecurrenceTwoPhaseTurbulenceModels diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Make/options b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Make/options new file mode 100644 index 00000000..4b197469 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/Make/options @@ -0,0 +1,27 @@ +EXE_INC = \ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/reactingTwoPhaseEulerFoam/twoPhaseSystem/lnInclude \ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/phaseSystems/lnInclude \ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/interfacialModels/lnInclude\ + -I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/interfacialCompositionModels/lnInclude \ + -I$(LIB_SRC)/transportModels/compressible/lnInclude \ + -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \ + -I$(LIB_SRC)/transportModels/incompressible/transportModel \ + -I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ + -I$(LIB_SRC)/TurbulenceModels/phaseCompressible/lnInclude \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I../recurrenceTurbulenceModel/lnInclude \ + -I../../../../src/recurrence/lnInclude + +LIB_LIBS = \ + -lreactingPhaseSystem \ + -lreactingTwoPhaseSystem \ + -lreactingEulerianInterfacialModels \ + -lreactingEulerianInterfacialCompositionModels \ + -lfiniteVolume \ + -lfvOptions \ + -lmeshTools \ + -L$(FOAM_USER_LIBBIN) \ + -lrecurrence \ + -lreactingTwoPhaseSystem diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/ReadMe.md b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/ReadMe.md new file mode 100644 index 00000000..af536ca3 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/ReadMe.md @@ -0,0 +1,107 @@ +# Recurrence-based, multi-phase turbulence modelling + +This model implements recurrence-based turbulence models, i.e. the fundamental +turbulent field quantities are read from the data base and are not solved for. +All derived field quantities are computed just in the same way as the proper +turbulence models do. By deriving the recurrence-based turbulence models from +somewhere up the family tree of OpenFOAM's turbulence model class hierarchy, +the recurrence-based turbulence models are fully compatible with OpenFOAM's +generic treatment of turbulence modelling, i.e. solvers and libraries interact +with references to a generic base type of the actual turbulence model. Hence, +solvers and libraries may remain blissfully ignorant of the actual turbulence +model in use. + +For laminar phases no special treatment is necessary, as the *laminar* +turbulence model does not compute any fields. + + +## Development notes + +The initial development covers only a small number of turbulence models. + + +## Notes on usage + +The turbulence model in use for the recurrence run must be the recurrence-based +equivalent of the turbulence model used for generating the data base, i.e. if +the data base was computed using the *kEpsilon* model, then the recurrence solver +is to employ the *recurrenceKEpsilon* turbulence model. This model will read +the relevant model coefficients from the *turbulenceProperties* dictionary, and +make sure that the turbulent fields `k` and `epsilon` are contained in the data +base. + +Whenever, the solver or a library calls `turbulence->nut()` to access the +turbulent viscosity, the recurrence-based kEpsilon model will compute `nut` +according to kEpsilon's relations `nut = Cmu*sqr(k)/epsilon`, with the fields +`k` and `epsilon` being from the current snapshot provided by the recurrence model. + +Thus, the fundamental turbulent field quantities of the employed turbulence model +have to be added to the *volScalarFields* list in the `recProperties` dictionary +controlling the recurrence model. This will ensure that the turbulent field +quantities are read from the data base. + + +## Notes on the implementation + +The base class implements the method `void setRecurrenceBasePtr(recBase*)`, which +is used to give the recurrence-based turbulence models a reference (technically +a pointer) to the recurrence model. Thus, after construction of the turbulence +models and the recurrence model, `setRecurrenceBasePtr()` needs to be called as +the pointer to the recurrence model is initialized by the constructor with `NULL`. +Trying to access the recurrence model from within the recurrence-based turbulence +model prior to setting the pointer to the recurrence model with +`setRecurrenceBasePtr()` will result in a segmentation fault. +In order to be able to call `setRecurrenceBasePtr()`, the generic reference to +the turbulence model needs to be converted into a reference of the base class' +type, i.e. `recurrenceTurbulenceModel`. +This unfortunate deviation from good standards, i.e. making full use of C++'s +polymorphism, should be the only instance of having to use non-pretty hacks. +However, apart from initialisation, i.e. setting the pointer to the recurrence +model, the recurrence-based turbulence models adhere to the generic interface of +OpenFOAM's turbulence models, and can be used as any other turbulence model. + + +The concrete implementations, e.g. *recurrenceKEpsilon*, use the method +`validate()` to check whether the underlying turbulent quantities are specified +for use in the data base in the *volScalarFields* list in the `recProperties` +dictionary. This method is part of the signature of the class `Foam::turbulenceModel`, +which is the very base class of all turbulence models in OpenFOAM. +In proper turbulence models, this method is used to check whether the internal +fields are properly initialized and to update all derived quantities. +In the solver, `validate()` must not be called prior to `setRecurrenceBasePtr()`, +as validate accesses the recurrence model. The wrong order of function calls will +result in a segmentation fault, as the pointer to the recurrence model is +initialized by the constructor with `NULL`. + + +The concrete implementations, e.g. *recurrenceKEpsilon*, use the method +`correct()` to update the turbulent field quantities from the data base, +and in turn update the derived quantities, such as `nut`. +This method is part of the signature of the class `Foam::turbulenceModel`, +which is the very base class of all turbulence models in OpenFOAM. +In proper turbulence models, this method is used to solve for the next time step. + + +## Compilation + +Source OpenFOAM and simply compile with + +```bash +./Allwclean +./Allwmake +``` + +The script `Allwclean` will clear all previous builds. This step is not needed for +first-time compilation. It is, however, recommended for subsequent compilations, as +it completely clears the slate. The script `Allwmake` will run the compilation for +the passive particle model. + + +## Required software + +This model has been tested with the following versions of OpenFOAM: + +* OpenFOAM-4.0 +* OpenFOAM-5.0 + + diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKEpsilon/recurrenceKEpsilon.C b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKEpsilon/recurrenceKEpsilon.C new file mode 100644 index 00000000..b0fb41a8 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKEpsilon/recurrenceKEpsilon.C @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "recurrenceKEpsilon.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + + +void Foam::RASModels::recurrenceKEpsilon::correctNut() +{ + this->nut_ = Cmu_*sqr(k_)/epsilon_; + this->nut_.correctBoundaryConditions(); +} + + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::RASModels::recurrenceKEpsilon::recurrenceKEpsilon +( + const volScalarField& alpha, + const volScalarField& rho, + const volVectorField& U, + const surfaceScalarField& alphaRhoPhi, + const surfaceScalarField& phi, + const transportModel& phase, + const word& propertiesName, + const word& type + +) +: + eddyViscosity>> + ( + type, + alpha, + rho, + U, + alphaRhoPhi, + phi, + phase, + propertiesName + ), + recurrenceTurbulenceModel(U.group()), + Cmu_ + ( + dimensioned::lookupOrAddToDict + ( + "Cmu", + this->coeffDict_, + 0.09 + ) + ), + k_ + ( + IOobject + ( + IOobject::groupName("k", U.group()), + this->runTime_.timeName(), + this->mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + this->mesh_, + dimensionedScalar("k0", dimensionSet(0,2,-2,0,0), 0.0) + ), + epsilon_ + ( + IOobject + ( + IOobject::groupName("epsilon", U.group()), + this->runTime_.timeName(), + this->mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + this->mesh_, + dimensionedScalar("eps0", dimensionSet(0,2,-3,0,0), 0.0) + ) +{ + if (type == typeName) + { + printCoeffs(type); + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + + +Foam::RASModels::recurrenceKEpsilon::~recurrenceKEpsilon() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::RASModels::recurrenceKEpsilon::read() +{ + if + ( + eddyViscosity>>::read() + ) + { + Cmu_.readIfPresent(this->coeffDict()); + + return true; + } + else + { + return false; + } +} + + +void Foam::RASModels::recurrenceKEpsilon::correct() +{ + // update turbulence fields + recurrenceBasePtr_->recM().exportVolScalarField("k."+group_, this->k_); + recurrenceBasePtr_->recM().exportVolScalarField("epsilon."+group_, this->epsilon_); + + // update nut + correctNut(); +} + + +void Foam::RASModels::recurrenceKEpsilon::validate() +{ + /* + Check whether k and epsilon are included in the dataBase. + The check only makes sure that these fields are included in the + volScalarFields list of recProperties. + Whether the fields are actually contained in the dataBase is + done by the recurrenceModel itself. + */ + bool foundK(false); + bool foundEpsilon(false); + + wordList fieldNames(recurrenceBasePtr_->recM().volScalarFieldNames()); + + forAll(fieldNames, i) + { + word curFieldName = fieldNames[i]; + + if (curFieldName == k_.name()) + { + foundK = true; + } + + if (curFieldName == epsilon_.name()) + { + foundEpsilon = true; + } + + + } + + if (not (foundK and foundEpsilon)) + { + FatalError + << "Fields " << k_.name() << " and " << epsilon_.name() + << " not specified in the volScalarFields list of recProperties!" << nl + << "volScalarFields : " << fieldNames << nl + << "Add these fields and make sure they are contained in the dataBase." << nl + << exit(FatalError); + } +} + + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKEpsilon/recurrenceKEpsilon.H b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKEpsilon/recurrenceKEpsilon.H new file mode 100644 index 00000000..24b9ed38 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKEpsilon/recurrenceKEpsilon.H @@ -0,0 +1,161 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Class + Foam::recurrenceKEpsilon + +Description + recurrence-based kEpsilon turbulence model + + This model provides kEpslion's turbulence quantities that were computed + elsewhere, i.e. taken from the recurrence dataBase. + To be used by recurrence solvers. + +SourceFiles + recurrenceKEpsilon.C + +\*---------------------------------------------------------------------------*/ + +#ifndef recurrenceKEpsilon_H +#define recurrenceKEpsilon_H + +#include "RASModel.H" +#include "eddyViscosity.H" +#include "phaseCompressibleTurbulenceModel.H" +#include "EddyDiffusivity.H" + +#include "recurrenceTurbulenceModel.H" + +#include "autoPtr.H" + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace RASModels +{ + +/*---------------------------------------------------------------------------*\ + Class recurrenceKEpsilon Declaration +\*---------------------------------------------------------------------------*/ + +class recurrenceKEpsilon +: + public eddyViscosity>>, + public recurrenceTurbulenceModel +{ + // Private data + + // Private Member Functions + + + //- Disallow default bitwise copy construct + recurrenceKEpsilon(const recurrenceKEpsilon&); + + //- Disallow default bitwise assignment + void operator=(const recurrenceKEpsilon&); + + +protected: + + // Protected data + + // Model coefficients + + dimensionedScalar Cmu_; + + // Fields + + volScalarField k_; + volScalarField epsilon_; + + // Protected Member Functions + + virtual void correctNut(); + + +public: + + + //- Runtime type information + TypeName("recurrenceKEpsilon"); + + + // Constructors + + //- Construct from components + recurrenceKEpsilon + ( + const volScalarField& alpha, + const volScalarField& rho, + const volVectorField& U, + const surfaceScalarField& alphaRhoPhi, + const surfaceScalarField& phi, + const phaseModel& transport, + const word& propertiesName = turbulenceModel::propertiesName, + const word& type = typeName + ); + + + + //- Destructor + virtual ~recurrenceKEpsilon(); + + + // Member Functions + + //- Re-read model coefficients if they have changed + virtual bool read(); + + + //- Return the turbulence kinetic energy + virtual tmp k() const + { + return k_; + } + + //- Return the turbulence kinetic energy dissipation rate + virtual tmp epsilon() const + { + return epsilon_; + } + + //- Update the turbulent fields + virtual void correct(); + + //- Check model settings + virtual void validate(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace RASModels +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKOmega/recurrenceKOmega.C b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKOmega/recurrenceKOmega.C new file mode 100644 index 00000000..fc58a1ba --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKOmega/recurrenceKOmega.C @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "recurrenceKOmega.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + + +void Foam::RASModels::recurrenceKOmega::correctNut() +{ + this->nut_ = k_/omega_; + this->nut_.correctBoundaryConditions(); +} + + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::RASModels::recurrenceKOmega::recurrenceKOmega +( + const volScalarField& alpha, + const volScalarField& rho, + const volVectorField& U, + const surfaceScalarField& alphaRhoPhi, + const surfaceScalarField& phi, + const transportModel& phase, + const word& propertiesName, + const word& type + +) +: + eddyViscosity>> + ( + type, + alpha, + rho, + U, + alphaRhoPhi, + phi, + phase, + propertiesName + ), + recurrenceTurbulenceModel(U.group()), + Cmu_ + ( + dimensioned::lookupOrAddToDict + ( + "Cmu", + this->coeffDict_, + 0.09 + ) + ), + k_ + ( + IOobject + ( + IOobject::groupName("k", U.group()), + this->runTime_.timeName(), + this->mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + this->mesh_, + dimensionedScalar("k0", dimensionSet(0,2,-2,0,0), 0.0) + ), + omega_ + ( + IOobject + ( + IOobject::groupName("omega", U.group()), + this->runTime_.timeName(), + this->mesh_, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + this->mesh_, + dimensionedScalar("om0", dimensionSet(0,0,-1,0,0), 0.0) + ) +{ + if (type == typeName) + { + printCoeffs(type); + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + + +Foam::RASModels::recurrenceKOmega::~recurrenceKOmega() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::RASModels::recurrenceKOmega::read() +{ + if + ( + eddyViscosity>>::read() + ) + { + Cmu_.readIfPresent(this->coeffDict()); + + return true; + } + else + { + return false; + } +} + + +void Foam::RASModels::recurrenceKOmega::correct() +{ + // update turbulence fields + recurrenceBasePtr_->recM().exportVolScalarField("k."+group_, this->k_); + recurrenceBasePtr_->recM().exportVolScalarField("omega."+group_, this->omega_); + + // update nut + correctNut(); +} + + +void Foam::RASModels::recurrenceKOmega::validate() +{ + /* + Check whether k and omega are included in the dataBase. + The check only makes sure that these fields are included in the + volScalarFields list of recProperties. + Whether the fields are actually contained in the dataBase is + done by the recurrenceModel itself. + */ + bool foundK(false); + bool foundOmega(false); + + wordList fieldNames(recurrenceBasePtr_->recM().volScalarFieldNames()); + + forAll(fieldNames, i) + { + word curFieldName = fieldNames[i]; + + if (curFieldName == k_.name()) + { + Info << "Found " << k_.name()<< endl; + foundK = true; + } + + if (curFieldName == omega_.name()) + { + Info << "Found " << omega_.name()<< endl; + foundOmega = true; + } + } + + if (not (foundK and foundOmega)) + { + FatalError + << "Fields " << k_.name() << " and " << omega_.name() + << " not specified in the volScalarFields list of recProperties!" << nl + << "volScalarFields : " << fieldNames << nl + << "Add these fields and make sure they are contained in the dataBase." << nl + << exit(FatalError); + } +} + + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKOmega/recurrenceKOmega.H b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKOmega/recurrenceKOmega.H new file mode 100644 index 00000000..bc89a42b --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceKOmega/recurrenceKOmega.H @@ -0,0 +1,188 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Class + Foam::recurrenceKOmega + +Description + recurrence-based kOmega turbulence model + + This model provides kOmega's turbulence quantities that were computed + elsewhere, i.e. taken from the recurrence dataBase + To be used by recurrence solvers + +SourceFiles + recurrenceKOmega.C + +\*---------------------------------------------------------------------------*/ + +#ifndef recurrenceKOmega_H +#define recurrenceKOmega_H + +#include "RASModel.H" +#include "eddyViscosity.H" +#include "phaseCompressibleTurbulenceModel.H" +#include "EddyDiffusivity.H" + +#include "recurrenceTurbulenceModel.H" + +#include "autoPtr.H" + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace RASModels +{ + +/*---------------------------------------------------------------------------*\ + Class recurrenceKOmega Declaration +\*---------------------------------------------------------------------------*/ + +class recurrenceKOmega +: + public eddyViscosity>>, + public recurrenceTurbulenceModel +{ + // Private data + + // Private Member Functions + + + //- Disallow default bitwise copy construct + recurrenceKOmega(const recurrenceKOmega&); + + //- Disallow default bitwise assignment + void operator=(const recurrenceKOmega&); + + +protected: + + // Protected data + + // Model coefficients + + dimensionedScalar Cmu_; + + // Fields + + volScalarField k_; + volScalarField omega_; + + // Protected Member Functions + + virtual void correctNut(); + + +public: + + + //- Runtime type information + TypeName("recurrenceKOmega"); + + + // Constructors + + //- Construct from components + recurrenceKOmega + ( + const volScalarField& alpha, + const volScalarField& rho, + const volVectorField& U, + const surfaceScalarField& alphaRhoPhi, + const surfaceScalarField& phi, + const phaseModel& transport, + const word& propertiesName = turbulenceModel::propertiesName, + const word& type = typeName + ); + + + + //- Destructor + virtual ~recurrenceKOmega(); + + + // Member Functions + + //- Re-read model coefficients if they have changed + virtual bool read(); + + + //- Return the turbulence kinetic energy + virtual tmp k() const + { + return k_; + } + + //- Return the turbulence specific dissipation rate + virtual tmp omega() const + { + return omega_; + } + + //- Return the turbulence kinetic energy dissipation rate + virtual tmp epsilon() const + { + return tmp + ( + new volScalarField + ( + IOobject + ( + "epsilon", + this->mesh_.time().timeName(), + this->mesh_ + ), + Cmu_*k_*omega_, + omega_.boundaryField().types() + ) + ); + } + + //- Update the turbulent fields + virtual void correct(); + + //- Check model settings + virtual void validate(); + + + // Setters + + void setRecurrenceBasePtr(recBase* recurrenceBasePtr) + { + recurrenceBasePtr_ = recurrenceBasePtr; + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace RASModels +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceSmagorinsky/recurrenceSmagorinsky.C b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceSmagorinsky/recurrenceSmagorinsky.C new file mode 100644 index 00000000..d51d513e --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceSmagorinsky/recurrenceSmagorinsky.C @@ -0,0 +1,158 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "recurrenceSmagorinsky.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +Foam::tmp Foam::LESModels::recurrenceSmagorinsky::k +( + const tmp& gradU +) const +{ + volSymmTensorField D(symm(gradU)); + + volScalarField a(this->Ce_/this->delta()); + volScalarField b((2.0/3.0)*tr(D)); + volScalarField c(2*Ck_*this->delta()*(dev(D) && D)); + + return tmp + ( + new volScalarField + ( + IOobject + ( + IOobject::groupName("k", this->U_.group()), + this->runTime_.timeName(), + this->mesh_ + ), + sqr((-b + sqrt(sqr(b) + 4*a*c))/(2*a)) + ) + ); +} + + +void Foam::LESModels::recurrenceSmagorinsky::correctNut() +{ + volScalarField k(this->k(fvc::grad(this->U_))); + + this->nut_ = Ck_*this->delta()*sqrt(k); + this->nut_.correctBoundaryConditions(); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::LESModels::recurrenceSmagorinsky::recurrenceSmagorinsky +( + const volScalarField& alpha, + const volScalarField& rho, + const volVectorField& U, + const surfaceScalarField& alphaRhoPhi, + const surfaceScalarField& phi, + const transportModel& phase, + const word& propertiesName, + const word& type +) +: + LESeddyViscosity> + ( + type, + alpha, + rho, + U, + alphaRhoPhi, + phi, + phase, + propertiesName + ), + recurrenceTurbulenceModel(U.group()), + Ck_ + ( + dimensioned::lookupOrAddToDict + ( + "Ck", + this->coeffDict_, + 0.094 + ) + ) +{ + if (type == typeName) + { + this->printCoeffs(type); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::LESModels::recurrenceSmagorinsky::read() +{ + if (LESeddyViscosity>::read()) + { + Ck_.readIfPresent(this->coeffDict()); + + return true; + } + else + { + return false; + } +} + + +Foam::tmp Foam::LESModels::recurrenceSmagorinsky::epsilon() const +{ + volScalarField k(this->k(fvc::grad(this->U_))); + + return tmp + ( + new volScalarField + ( + IOobject + ( + IOobject::groupName("epsilon", this->U_.group()), + this->runTime_.timeName(), + this->mesh_ + ), + this->Ce_*k*sqrt(k)/this->delta() + ) + ); +} + + +void Foam::LESModels::recurrenceSmagorinsky::correct() +{ + // update nut + correctNut(); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceSmagorinsky/recurrenceSmagorinsky.H b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceSmagorinsky/recurrenceSmagorinsky.H new file mode 100644 index 00000000..3cbc15b4 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceSmagorinsky/recurrenceSmagorinsky.H @@ -0,0 +1,146 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Class + Foam::LESModels::recurrenceSmagorinsky + +Description + The recurrenceSmagorinsky SGS model. + + This model provides Smagorinsky's turbulence quantities. + To be used by recurrence solvers. + +SourceFiles + recurrenceSmagorinsky.C + +\*---------------------------------------------------------------------------*/ + +#ifndef recurrenceSmagorinsky_H +#define recurrenceSmagorinsky_H + +#include "LESModel.H" +#include "LESeddyViscosity.H" +#include "phaseCompressibleTurbulenceModel.H" +#include "EddyDiffusivity.H" + +#include "recurrenceTurbulenceModel.H" + +#include "autoPtr.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace LESModels +{ + +/*---------------------------------------------------------------------------*\ + Class recurrenceSmagorinsky Declaration +\*---------------------------------------------------------------------------*/ + +class recurrenceSmagorinsky +: + public LESeddyViscosity>, + public recurrenceTurbulenceModel +{ + // Private Member Functions + + // Disallow default bitwise copy construct and assignment + recurrenceSmagorinsky(const recurrenceSmagorinsky&); + void operator=(const recurrenceSmagorinsky&); + + +protected: + + // Protected data + + dimensionedScalar Ck_; + + + // Protected Member Functions + + //- Return SGS kinetic energy + // calculated from the given velocity gradient + tmp k(const tmp& gradU) const; + + //- Update the SGS eddy viscosity + virtual void correctNut(); + + +public: + + + //- Runtime type information + TypeName("recurrenceSmagorinsky"); + + + // Constructors + + //- Construct from components + recurrenceSmagorinsky + ( + const volScalarField& alpha, + const volScalarField& rho, + const volVectorField& U, + const surfaceScalarField& alphaRhoPhi, + const surfaceScalarField& phi, + const phaseModel& transport, + const word& propertiesName = turbulenceModel::propertiesName, + const word& type = typeName + ); + + + //- Destructor + virtual ~recurrenceSmagorinsky() + {} + + + // Member Functions + + //- Read model coefficients if they have changed + virtual bool read(); + + //- Return SGS kinetic energy + virtual tmp k() const + { + return k(fvc::grad(this->U_)); + } + + //- Return sub-grid disipation rate + virtual tmp epsilon() const; + + //- Correct Eddy-Viscosity and related properties + virtual void correct(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace LESModels +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceTurbulenceModel/recurrenceTurbulenceModel.C b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceTurbulenceModel/recurrenceTurbulenceModel.C new file mode 100644 index 00000000..731d92c0 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceTurbulenceModel/recurrenceTurbulenceModel.C @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "recurrenceTurbulenceModel.H" + + +namespace Foam +{ + defineTypeNameAndDebug(recurrenceTurbulenceModel, 0); +} + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + + +Foam::recurrenceTurbulenceModel::recurrenceTurbulenceModel +( + const word group +) +: + recurrenceBasePtr_(NULL), + group_(group) +{ +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::recurrenceTurbulenceModel::~recurrenceTurbulenceModel() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + + + + + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceTurbulenceModel/recurrenceTurbulenceModel.H b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceTurbulenceModel/recurrenceTurbulenceModel.H new file mode 100644 index 00000000..1a532e36 --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceTurbulenceModel/recurrenceTurbulenceModel.H @@ -0,0 +1,124 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Class + Foam::recurrenceTurbulenceModel + +Description + recurrence-based turbulence model base class + + This turbulence model class provides a framework for derived turbulence + models to provide turbulence quantities that were computed elsewhere, + i.e. taken from the recurrence dataBase. + + A concrete recurrence-based turbulence model implementation, e.g. recurrenceKEpsilon, + needs to be derived from the base class of the original turbulence model + and this class. This class provides the link to the recurrence model. The original + base class provides the proper turbulence modelling interfaces of OpenFOAM's + turbulence modelling framework. + + To be used by recurrence solvers. + +SourceFiles + recurrenceTurbulenceModel.C + +\*---------------------------------------------------------------------------*/ + +#ifndef recurrenceTurbulenceModel_H +#define recurrenceTurbulenceModel_H + +#include "recBase.H" +#include "recModel.H" + +#include "autoPtr.H" + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class recurrenceTurbulenceModel Declaration +\*---------------------------------------------------------------------------*/ + +class recurrenceTurbulenceModel +{ + // Private Member Functions + + + //- Disallow default bitwise copy construct + recurrenceTurbulenceModel(const recurrenceTurbulenceModel&); + + //- Disallow default bitwise assignment + void operator=(const recurrenceTurbulenceModel&); + + +protected: + + // Protected data + + recBase* recurrenceBasePtr_; + const word group_; + + + // Protected Member Functions + + +public: + + //- Runtime type information + TypeName("recurrenceTurbulenceModel"); + + + // Constructors + + //- Construct from components + recurrenceTurbulenceModel + ( + const word group + ); + + + //- Destructor + virtual ~recurrenceTurbulenceModel(); + + + // Member Functions + + void setRecurrenceBasePtr(recBase* recurrenceBasePtr) + { + recurrenceBasePtr_ = recurrenceBasePtr; + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceTurbulenceModels.C b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceTurbulenceModels.C new file mode 100644 index 00000000..a0fcdf7a --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/recurrenceTurbulence/recurrenceTurbulenceModels.C @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2014-2015 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "phaseCompressibleTurbulenceModel.H" +#include "addToRunTimeSelectionTable.H" +#include "makeTurbulenceModel.H" + +#include "laminar.H" +#include "RASModel.H" +#include "LESModel.H" + +#include "recurrenceKEpsilon.H" +#include "recurrenceKOmega.H" +#include "recurrenceSmagorinsky.H" + + + +// Instructions for OpenFOAM-5.0 +/*makeTurbulenceModelTypes +( + volScalarField, + volScalarField, + compressibleTurbulenceModel, + PhaseCompressibleTurbulenceModel, + ThermalDiffusivity, + phaseModel +); + + +makeTurbulenceModel +(phaseModelPhaseCompressibleTurbulenceModel, RAS, recurrenceKEpsilon); + +makeTurbulenceModel +(phaseModelPhaseCompressibleTurbulenceModel, RAS, recurrenceKOmega); + +makeTurbulenceModel +(phaseModelPhaseCompressibleTurbulenceModel, LES, recurrenceSmagorinsky); +*/ + + + +// Instructions for OpenFOAM-4.0 +makeBaseTurbulenceModel +( + volScalarField, + volScalarField, + compressibleTurbulenceModel, + PhaseCompressibleTurbulenceModel, + ThermalDiffusivity, + phaseModel +); + +#define makeRASModel(Type) \ + makeTurbulenceModel \ + (phaseModelPhaseCompressibleTurbulenceModel, RAS, Type) + +#define makeLESModel(Type) \ + makeTurbulenceModel \ + (phaseModelPhaseCompressibleTurbulenceModel, LES, Type) + +makeRASModel(recurrenceKEpsilon); + +makeRASModel(recurrenceKOmega); + +makeLESModel(recurrenceSmagorinsky); + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/testTwoFluidRecurrenceTurbulence.C b/applications/solvers/testTwoFluidRecurrenceTurbulence/testTwoFluidRecurrenceTurbulence.C new file mode 100644 index 00000000..eeeabb0c --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/testTwoFluidRecurrenceTurbulence.C @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Application + testTwoFluidRecurrenceTurbulence + +Description + A modified variant of the two-fluid, recurrence model A solver + with the extension of recurrence-based, multi-phase turbulence modelling. + This application is used to test whether turbulent fields can be provided + by the recurrence-based turbulence models. + + Run this test application in a recurrence case, with turbulence enabled and + the necessary turbulent field quantities present in the data base. + + Note the initialisation in checkTurbulenceModels.H + Updating the turbulence model is done by calling phaseX.correctTurbulence() + in the file readFields.H + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" +#include "twoPhaseSystem.H" +#include "phaseCompressibleTurbulenceModel.H" +#include "pimpleControl.H" +#include "localEulerDdtScheme.H" +#include "fvcSmooth.H" + +#include "recBase.H" +#include "recModel.H" + +#include "recurrenceTurbulenceModel.H" + +/* // uncomment for OpenFOAM-5.0 +namespace Foam +{ + tmp byDt(const volScalarField& vf) + { + if (fv::localEulerDdt::enabled(vf.mesh())) + { + return fv::localEulerDdt::localRDeltaT(vf.mesh())*vf; + } + else + { + return vf/vf.mesh().time().deltaT(); + } + } + + tmp byDt(const surfaceScalarField& sf) + { + if (fv::localEulerDdt::enabled(sf.mesh())) + { + return fv::localEulerDdt::localRDeltaTf(sf.mesh())*sf; + } + else + { + return sf/sf.mesh().time().deltaT(); + } + } +} +*/ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + #include "postProcess.H" + + #include "setRootCase.H" + #include "createTime.H" + #include "createMesh.H" + #include "createControl.H" + #include "createTimeControls.H" + #include "createRDeltaT.H" // remove for OpenFOAM-5.0 + #include "createFields.H" + #include "createFieldRefs.H" + + #include "createTransportFields.H" + + if (!LTS) + { + #include "CourantNo.H" + #include "setInitialDeltaT.H" + } + + Switch faceMomentum + ( + pimple.dict().lookupOrDefault("faceMomentum", false) + ); + + + recBase recurrenceBase(mesh); + + #include "checkTurbulenceModels.H" + + #include "pUf/createDDtU.H" + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info<< "\nStarting recurrence-based time loop\n" << endl; + + label recTimeIndex(0); + scalar recTimeStep_=recurrenceBase.recM().recTimeStep(); + + while (runTime.run()) + { + #include "readTimeControls.H" + + #include "CourantNos.H" + #include "setDeltaT.H" + + runTime++; + Info<< "Time = " << runTime.timeName() << nl << endl; + + + #include "CEqn.H" + + + if ( runTime.timeOutputValue() - (recTimeIndex+1)*recTimeStep_ + 1.0e-5 > 0.0 ) + { + Info << "Updating fields at run time " << runTime.timeOutputValue() + << " corresponding to recurrence time " << (recTimeIndex+1)*recTimeStep_ << ".\n" << endl; + + recurrenceBase.updateRecFields(); + #include "readFields.H" + recTimeIndex++; + } + + + runTime.write(); + + #include "writeCField.H" + + Info<< "ExecutionTime = " + << runTime.elapsedCpuTime() + << " s\n\n" << endl; + } + + Info<< "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/solvers/testTwoFluidRecurrenceTurbulence/writeCField.H b/applications/solvers/testTwoFluidRecurrenceTurbulence/writeCField.H new file mode 100644 index 00000000..b8fdf4ca --- /dev/null +++ b/applications/solvers/testTwoFluidRecurrenceTurbulence/writeCField.H @@ -0,0 +1,12 @@ +/* ---------------------------------------------- + Write averaged particle volume fraction +---------------------------------------------- */ + +// essential information +Info << "Total mass :"; +Info << tab << sum(C*rhoCarrier*alphaCarrier*mesh.V()); +Info << endl; + +Info << "Total Carrier mass :"; +Info << tab << sum(rhoCarrier*alphaCarrier*mesh.V()); +Info << endl; diff --git a/applications/utilities/mapDataBase/mapFieldData.sh b/applications/utilities/mapDataBase/mapFieldData.sh new file mode 100755 index 00000000..2b58b8dc --- /dev/null +++ b/applications/utilities/mapDataBase/mapFieldData.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# Source run functions +. $WM_PROJECT_DIR/bin/tools/RunFunctions + +# to be executed from one level above the source directory + +if [ $# -eq 0 ] + then + sourceName="dataBase" + targetName="dataBaseCoarse" + else + sourceName=$1 + targetName=$2 +fi + +cd $sourceName + +for time in * +do + if [ $time != "system" ] && [ $time != "constant" ]; + then + cd ../$targetName + echo "Found $time." + sed -i "/^startTime/c\startTime \t$time;" ./system/controlDict + grep 'startTime' ./system/controlDict + mapFields ../$sourceName -sourceTime $time -consistent + cd ../$sourceName + fi +done + diff --git a/applications/utilities/rBaseMirror/mirrorProperties b/applications/utilities/rBaseMirror/mirrorProperties new file mode 100755 index 00000000..255f58c7 --- /dev/null +++ b/applications/utilities/rBaseMirror/mirrorProperties @@ -0,0 +1,39 @@ +/*---------------------------------------------------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: 1.4 | +| \\ / A nd | Web: http://www.openfoam.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ + + +FoamFile +{ + version 2.0; + format ascii; + + root ""; + case ""; + instance ""; + local ""; + + class dictionary; + object mirrorProperties; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//===========================================================================// +// sub-models & settings + + +refPoint (0 0 0); + +refDirection (1 0 0); + +fieldName U; + +dataBaseName dataBase; + + +// ************************************************************************* // diff --git a/applications/utilities/rBaseMirror/rBaseMirrorScalar/Make/files b/applications/utilities/rBaseMirror/rBaseMirrorScalar/Make/files new file mode 100644 index 00000000..b04d6113 --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorScalar/Make/files @@ -0,0 +1,3 @@ +rBaseMirrorScalar.C + +EXE=$(CFDEM_APP_DIR)/rBaseMirrorScalar diff --git a/applications/utilities/rBaseMirror/rBaseMirrorScalar/Make/options b/applications/utilities/rBaseMirror/rBaseMirrorScalar/Make/options new file mode 100644 index 00000000..e4e2bed2 --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorScalar/Make/options @@ -0,0 +1,16 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + + +EXE_INC = \ + $(PFLAGS) \ + -I$(LIB_SRC)/finiteVolume/cfdTools \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/sampling/lnInclude \ + -I$(LIB_SRC)/fvOptions/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lmeshTools \ + -lsampling \ + -lfvOptions diff --git a/applications/utilities/rBaseMirror/rBaseMirrorScalar/createFields.H b/applications/utilities/rBaseMirror/rBaseMirrorScalar/createFields.H new file mode 100644 index 00000000..91f96378 --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorScalar/createFields.H @@ -0,0 +1,17 @@ + IOdictionary mirrorProperties + ( + IOobject + ( + "mirrorProperties", + mesh.time().constant(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ); + + vector refPoint(mirrorProperties.lookup("refPoint")); + vector refDirection(mirrorProperties.lookup("refDirection")); + + word fieldName(mirrorProperties.lookup("fieldName")); + word dataBaseName(mirrorProperties.lookup("dataBaseName")); diff --git a/applications/utilities/rBaseMirror/rBaseMirrorScalar/rBaseMirrorScalar.C b/applications/utilities/rBaseMirror/rBaseMirrorScalar/rBaseMirrorScalar.C new file mode 100644 index 00000000..c4b6be3e --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorScalar/rBaseMirrorScalar.C @@ -0,0 +1,136 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Application + rBaseMirror + + +Description + Read time series and extend it by mirrored fields if geometry possesses + the same symmetry + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noParallel(); + timeSelector::addOptions(); + + #include "setRootCase.H" + #include "createTime.H" + + // read in start and end time from controlDict + + scalar startTime=runTime.startTime().value(); + scalar endTime=runTime.endTime().value(); + scalar origTimeRange = endTime - startTime; + + Info << "start time = " << runTime.startTime() << endl; + Info << "end time = " << runTime.endTime() << endl; + + // check which time directories are present + // instantList timeDirs = timeSelector::select0(runTime, args); + // runTime.setTime(timeDirs[0], 0); + + #include "createMesh.H" + + #include "createFields.H" + + Foam::Time recTime(fileName(dataBaseName), "", "../system", "../constant", false); + instantList timeDirs(recTime.times()); + recTime.setTime(timeDirs[0],0); + + #include "readFields.H" + + Info << fieldName << endl; + + volScalarField transformedField = origField; + + scalar t; + + label shiftedTimeI = 0; + + // check number of time directories + label shift = 0; + forAll(timeDirs, timeI) + { + + if (recTime.timeName() == "constant") continue; + recTime.setTime(timeDirs[timeI], timeI); + t = recTime.value(); + if(t < startTime) continue; + if(t > endTime) continue; + shift++; + } + + scalar dt = origTimeRange / (shift - 1.0); + recTime.setEndTime(startTime + 2 * origTimeRange + dt); + + label cellI_transformed = -1; + forAll(timeDirs, timeI) + { + + recTime.setTime(timeDirs[timeI], timeI); + t = recTime.value(); + if(t < startTime) continue; + if(t > endTime) continue; + Info << "time = " << t << ", time index = " << timeI << endl; + + #include "readFields.H" + + forAll(transformedField, cellI) + { + vector position = mesh.C()[cellI]; + vector transformedPosition = 2 * ((refPoint - position) & refDirection) * refDirection / (refDirection & refDirection) + position; + cellI_transformed = mesh.findCell(transformedPosition); + if(cellI_transformed < 0) + { + Info << "Couldn't find transformed cell. Stopping." << endl; + return 0; + } + + scalar value = origField[cellI_transformed]; + scalar transformedValue = value; + + transformedField[cellI] = transformedValue; + } + + shiftedTimeI = timeI + shift; + t = recTime.value() + origTimeRange + dt; + runTime.setTime(t, shiftedTimeI); + Info << "creating transformed fields for time = " << t << ", time index = " << shiftedTimeI << endl; + transformedField.write(); + } + + Info << "\nEnd" << endl; + + return 0; +} + +// ************************************************************************* // diff --git a/applications/utilities/rBaseMirror/rBaseMirrorScalar/readFields.H b/applications/utilities/rBaseMirror/rBaseMirrorScalar/readFields.H new file mode 100644 index 00000000..5e0d9265 --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorScalar/readFields.H @@ -0,0 +1,13 @@ + + volScalarField origField + ( + IOobject + ( + fieldName, + recTime.timePath(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ), + mesh + ); diff --git a/applications/utilities/rBaseMirror/rBaseMirrorVec/Make/files b/applications/utilities/rBaseMirror/rBaseMirrorVec/Make/files new file mode 100644 index 00000000..41a5e605 --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorVec/Make/files @@ -0,0 +1,3 @@ +rBaseMirrorVec.C + +EXE=$(CFDEM_APP_DIR)/rBaseMirrorVec diff --git a/applications/utilities/rBaseMirror/rBaseMirrorVec/Make/options b/applications/utilities/rBaseMirror/rBaseMirrorVec/Make/options new file mode 100644 index 00000000..e4e2bed2 --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorVec/Make/options @@ -0,0 +1,16 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + + +EXE_INC = \ + $(PFLAGS) \ + -I$(LIB_SRC)/finiteVolume/cfdTools \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/sampling/lnInclude \ + -I$(LIB_SRC)/fvOptions/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lmeshTools \ + -lsampling \ + -lfvOptions diff --git a/applications/utilities/rBaseMirror/rBaseMirrorVec/createFields.H b/applications/utilities/rBaseMirror/rBaseMirrorVec/createFields.H new file mode 100644 index 00000000..91f96378 --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorVec/createFields.H @@ -0,0 +1,17 @@ + IOdictionary mirrorProperties + ( + IOobject + ( + "mirrorProperties", + mesh.time().constant(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ); + + vector refPoint(mirrorProperties.lookup("refPoint")); + vector refDirection(mirrorProperties.lookup("refDirection")); + + word fieldName(mirrorProperties.lookup("fieldName")); + word dataBaseName(mirrorProperties.lookup("dataBaseName")); diff --git a/applications/utilities/rBaseMirror/rBaseMirrorVec/rBaseMirrorVec.C b/applications/utilities/rBaseMirror/rBaseMirrorVec/rBaseMirrorVec.C new file mode 100644 index 00000000..c7fcb1d8 --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorVec/rBaseMirrorVec.C @@ -0,0 +1,134 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Application + rBaseMirror + +Description + Read time series and extend it by mirrored fields if geometry possesses + the same symmetry + +\*---------------------------------------------------------------------------*/ + +#include "fvCFD.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noParallel(); + timeSelector::addOptions(); + + #include "setRootCase.H" + #include "createTime.H" + + // read in start and end time from controlDict + + scalar startTime=runTime.startTime().value(); + scalar endTime=runTime.endTime().value(); + scalar origTimeRange = endTime - startTime; + + Info << "start time = " << runTime.startTime() << endl; + Info << "end time = " << runTime.endTime() << endl; + + // check which time directories are present + //instantList timeDirs = timeSelector::select0(runTime, args); + //runTime.setTime(timeDirs[0], 0); + + #include "createMesh.H" + + #include "createFields.H" + + Foam::Time recTime(fileName(dataBaseName), "", "../system", "../constant", false); + instantList timeDirs(recTime.times()); + recTime.setTime(timeDirs[0],0); + + #include "readFields.H" + + Info << fieldName << endl; + + volVectorField transformedField = origField; + + scalar t; + + label shiftedTimeI = 0; + + // check number of time directories + label shift = 0; + forAll(timeDirs, timeI) + { + + if (recTime.timeName() == "constant") continue; + recTime.setTime(timeDirs[timeI], timeI); + t = recTime.value(); + if(t < startTime) continue; + if(t > endTime) continue; + shift++; + } + + scalar dt = origTimeRange / (shift - 1.0); + recTime.setEndTime(startTime + 2 * origTimeRange + dt); + + label cellI_transformed = -1; + forAll(timeDirs, timeI) + { + recTime.setTime(timeDirs[timeI], timeI); + t = recTime.value(); + if(t < startTime) continue; + if(t > endTime) continue; + Info << "time = " << t << ", time index = " << timeI << endl; + + #include "readFields.H" + + forAll(transformedField, cellI) + { + vector position = mesh.C()[cellI]; + vector transformedPosition = 2 * ((refPoint - position) & refDirection) * refDirection / (refDirection & refDirection) + position; + cellI_transformed = mesh.findCell(transformedPosition); + if(cellI_transformed < 0) + { + Info << "Couldn't find transformed cell. Stopping." << endl; + return 0; + } + + vector value = origField[cellI_transformed]; + vector transformedValue = -2 * (value & refDirection) * refDirection / (refDirection & refDirection) + value; + + transformedField[cellI] = transformedValue; + } + + shiftedTimeI = timeI + shift; + t = recTime.value() + origTimeRange + dt; + runTime.setTime(t, shiftedTimeI); + Info << "creating transformed fields for time = " << t << ", time index = " << shiftedTimeI << endl; + transformedField.write(); + } + + Info << "\nEnd" << endl; + + return 0; +} + +// ************************************************************************* // diff --git a/applications/utilities/rBaseMirror/rBaseMirrorVec/readFields.H b/applications/utilities/rBaseMirror/rBaseMirrorVec/readFields.H new file mode 100644 index 00000000..d0fef922 --- /dev/null +++ b/applications/utilities/rBaseMirror/rBaseMirrorVec/readFields.H @@ -0,0 +1,14 @@ + +volVectorField origField + ( + IOobject + ( + fieldName, + recTime.timePath(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ), + mesh + ); + diff --git a/applications/utilities/rSmoother/Make/files b/applications/utilities/rSmoother/Make/files new file mode 100644 index 00000000..a48ff737 --- /dev/null +++ b/applications/utilities/rSmoother/Make/files @@ -0,0 +1,3 @@ +rSmoother.C + +EXE=$(CFDEM_APP_DIR)/rSmoother diff --git a/applications/utilities/rSmoother/Make/options b/applications/utilities/rSmoother/Make/options new file mode 100644 index 00000000..39b05d12 --- /dev/null +++ b/applications/utilities/rSmoother/Make/options @@ -0,0 +1,18 @@ +include $(CFDEM_ADD_LIBS_DIR)/additionalLibs + +EXE_INC = \ + -I$(CFDEM_OFVERSION_DIR) \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(CFDEM_SRC_DIR)/recurrence/lnInclude \ + +EXE_LIBS = \ + -L$(CFDEM_LIB_DIR)\ + -lrecurrence \ + -lfiniteVolume \ + -lmeshTools \ + -l$(CFDEM_LIB_NAME) \ + $(CFDEM_ADD_LIB_PATHS) \ + -lsampling \ + -lfvOptions \ +$(CFDEM_ADD_LIBS) diff --git a/applications/utilities/rSmoother/createFields.H b/applications/utilities/rSmoother/createFields.H new file mode 100644 index 00000000..edd9094c --- /dev/null +++ b/applications/utilities/rSmoother/createFields.H @@ -0,0 +1,28 @@ + IOdictionary recProperties + ( + IOobject + ( + "recProperties", + mesh.time().constant(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ) + ); + + + scalar threshold(readScalar(recProperties.lookup("threshold"))); + + volVectorField U_smooth + ( + IOobject + ( + "U_smooth", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + mesh, + dimensionedVector("zero", dimensionSet(0,1,-1,0,0,0,0), vector(0.0, 0.0, 0.0)) + ); diff --git a/applications/utilities/rSmoother/rSmoother.C b/applications/utilities/rSmoother/rSmoother.C new file mode 100644 index 00000000..41b3ce15 --- /dev/null +++ b/applications/utilities/rSmoother/rSmoother.C @@ -0,0 +1,90 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . + +Application + rSmoother + +Description + Loops over all recurrence times and averages fields over given similarity range + +\*---------------------------------------------------------------------------*/ + + #include "fvCFD.H" + #include "fvOptions.H" + +#include "recBase.H" +#include "recModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + #include "postProcess.H" + #include "setRootCase.H" + #include "createTime.H" + #include "createMesh.H" + #include "createControl.H" + #include "createFields.H" + + + recBase recurrenceBase(mesh); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + // set time step to that of recurrence database + runTime.setDeltaT(recurrenceBase.recM().recTimeStep()); + + // check start and end time + if (abs(runTime.startTime().value() - recurrenceBase.recM().recStartTime()) > 1e-5) + { + Info << "Stopping. Start time and database start time are different." << endl; + Info << "Start time = " << runTime.startTime().value() << endl; + Info << "Database start time = " << recurrenceBase.recM().recStartTime() << endl; + return 0; + } + + if (runTime.endTime().value() > recurrenceBase.recM().recEndTime()) + { + runTime.setEndTime(recurrenceBase.recM().recEndTime()); + Info << "End time set to database end time." << endl; + } + + label index = -1; + + Info << "\nSmoothing recurrence statistics\n" << endl; + + while (runTime.run()) + { + // runtime can't be larger than recurrence database size + index = runTime.timeIndex(); + #include "updateFields.H" + runTime++; + } + + Info << "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/utilities/rSmoother/updateFields.H b/applications/utilities/rSmoother/updateFields.H new file mode 100644 index 00000000..1e38f569 --- /dev/null +++ b/applications/utilities/rSmoother/updateFields.H @@ -0,0 +1,4 @@ +Info << "averaging fields for time = " << runTime.value() << ", time index = " << index << endl; + +recurrenceBase.recM().exportAveragedVolVectorField(U_smooth, "UMean", threshold, index); +U_smooth.write(); diff --git a/doc/_themes/lammps_theme/breadcrumbs.html b/doc/_themes/lammps_theme/breadcrumbs.html new file mode 100644 index 00000000..4681bb2c --- /dev/null +++ b/doc/_themes/lammps_theme/breadcrumbs.html @@ -0,0 +1,34 @@ + + + Docs » + {% for doc in parents %} + {{ doc.title }} » + {% endfor %} + {{ title }} + + {% if pagename != "search" %} + {% if display_github %} + Edit on GitHub + {% elif display_bitbucket %} + Edit on Bitbucket + {% elif show_source and source_url_prefix %} + View page source + {% elif show_source and has_source and sourcename %} + View page source + {% endif %} + Website + {% endif %} + + + + {% if next or prev %} + + {% endif %} + diff --git a/doc/_themes/lammps_theme/footer.html b/doc/_themes/lammps_theme/footer.html new file mode 100644 index 00000000..6347a440 --- /dev/null +++ b/doc/_themes/lammps_theme/footer.html @@ -0,0 +1,36 @@ + + diff --git a/doc/_themes/lammps_theme/layout.html b/doc/_themes/lammps_theme/layout.html new file mode 100644 index 00000000..f18123be --- /dev/null +++ b/doc/_themes/lammps_theme/layout.html @@ -0,0 +1,195 @@ +{# TEMPLATE VAR SETTINGS #} +{%- set url_root = pathto('', 1) %} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + + + + + + + {{ metatags }} + + {% block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {% endblock %} + + {# FAVICON #} + {% if favicon %} + + {% endif %} + + {# CSS #} + + {# OPENSEARCH #} + {% if not embedded %} + {% if use_opensearch %} + + {% endif %} + + {% endif %} + + {# RTD hosts this file, so just load on non RTD builds #} + {% if not READTHEDOCS %} + + {% endif %} + + {% for cssfile in css_files %} + + {% endfor %} + + {% for cssfile in extra_css_files %} + + {% endfor %} + + {%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} + {%- endblock %} + {%- block extrahead %} {% endblock %} + + {# Keep modernizr in head - http://modernizr.com/docs/#installing #} + + + + + + + + + {# SIDE NAV, TOGGLES ON MOBILE #} + + + {% block sidebartitle %} + + {% if logo and theme_logo_only %} + + {% else %} + {{ project }} + {% endif %} + + {% if logo %} + {# Not strictly valid HTML, but it's the only way to display/scale it properly, without weird scripting or heaps of work #} + + {% endif %} + + + {% if theme_display_version %} + {%- set nav_version = version %} + {% if READTHEDOCS and current_version %} + {%- set nav_version = current_version %} + {% endif %} + {% if nav_version %} + + {{ nav_version }} + + {% endif %} + {% endif %} + + {% include "searchbox.html" %} + + {% endblock %} + + + + {% block menu %} + {% set toctree = toctree(maxdepth=4, collapse=theme_collapse_navigation, includehidden=True) %} + {% if toctree %} + {{ toctree }} + {% else %} + + {{ toc }} + {% endif %} + {% endblock %} + + + + + + + {# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #} + + + {{ project }} + + + + {# PAGE CONTENT #} + + + {% include "breadcrumbs.html" %} + + + {% block body %}{% endblock %} + + + {% include "footer.html" %} + + + + + + + {% include "versions.html" %} + + {% if not embedded %} + + + {%- for scriptfile in script_files %} + + {%- endfor %} + + {% endif %} + + {# RTD hosts this file, so just load on non RTD builds #} + {% if not READTHEDOCS %} + + {% endif %} + + {# STICKY NAVIGATION #} + {% if theme_sticky_navigation %} + + {% endif %} + + {%- block footer %} {% endblock %} + + + diff --git a/doc/_themes/lammps_theme/layout_old.html b/doc/_themes/lammps_theme/layout_old.html new file mode 100644 index 00000000..deb8df2a --- /dev/null +++ b/doc/_themes/lammps_theme/layout_old.html @@ -0,0 +1,205 @@ +{# + basic/layout.html + ~~~~~~~~~~~~~~~~~ + + Master layout template for Sphinx themes. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- block doctype -%} + +{%- endblock %} +{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} +{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} +{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and + (sidebars != []) %} +{%- set url_root = pathto('', 1) %} +{# XXX necessary? #} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + +{%- macro relbar() %} + + {{ _('Navigation') }} + + {%- for rellink in rellinks %} + + {{ rellink[3] }} + {%- if not loop.first %}{{ reldelim2 }}{% endif %} + {%- endfor %} + {%- block rootrellink %} + {{ shorttitle|e }}{{ reldelim1 }} + {%- endblock %} + {%- for parent in parents %} + {{ parent.title }}{{ reldelim1 }} + {%- endfor %} + {%- block relbaritems %} {% endblock %} + + +{%- endmacro %} + +{%- macro sidebar() %} + {%- if render_sidebar %} + + + {%- block sidebarlogo %} + {%- if logo %} + + + + {%- endif %} + {%- endblock %} + {%- if sidebars != None %} + {#- new style sidebar: explicitly include/exclude templates #} + {%- for sidebartemplate in sidebars %} + {%- include sidebartemplate %} + {%- endfor %} + {%- else %} + {#- old style sidebars: using blocks -- should be deprecated #} + {%- block sidebartoc %} + {%- include "localtoc.html" %} + {%- endblock %} + {%- block sidebarrel %} + {%- include "relations.html" %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- include "sourcelink.html" %} + {%- endblock %} + {%- if customsidebar %} + {%- include customsidebar %} + {%- endif %} + {%- block sidebarsearch %} + {%- include "searchbox.html" %} + {%- endblock %} + {%- endif %} + + + {%- endif %} +{%- endmacro %} + +{%- macro script() %} + + {%- for scriptfile in script_files %} + + {%- endfor %} +{%- endmacro %} + +{%- macro css() %} + + + {%- for cssfile in css_files %} + + {%- endfor %} +{%- endmacro %} + + + + + {{ metatags }} + {%- block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {%- endblock %} + {{ css() }} + {%- if not embedded %} + {{ script() }} + {%- if use_opensearch %} + + {%- endif %} + {%- if favicon %} + + {%- endif %} + {%- endif %} +{%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} +{%- endblock %} +{%- block extrahead %} {% endblock %} + + +{%- block header %}{% endblock %} + +{%- block relbar1 %}{{ relbar() }}{% endblock %} + +{%- block content %} + {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %} + + + {%- block document %} + + {%- if render_sidebar %} + + {%- endif %} + + {% block body %} {% endblock %} + + {%- if render_sidebar %} + + {%- endif %} + + {%- endblock %} + + {%- block sidebar2 %}{{ sidebar() }}{% endblock %} + + +{%- endblock %} + +{%- block relbar2 %}{{ relbar() }}{% endblock %} + +{%- block footer %} + + asdf asdf asdf asdf 22 +{%- endblock %} + + + diff --git a/doc/_themes/lammps_theme/search.html b/doc/_themes/lammps_theme/search.html new file mode 100644 index 00000000..e3aa9b5c --- /dev/null +++ b/doc/_themes/lammps_theme/search.html @@ -0,0 +1,50 @@ +{# + basic/search.html + ~~~~~~~~~~~~~~~~~ + + Template for the search page. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- extends "layout.html" %} +{% set title = _('Search') %} +{% set script_files = script_files + ['_static/searchtools.js'] %} +{% block footer %} + + {# this is used when loading the search index using $.ajax fails, + such as on Chrome for documents on localhost #} + + {{ super() }} +{% endblock %} +{% block body %} + + + + {% trans %}Please activate JavaScript to enable the search + functionality.{% endtrans %} + + + + + {% if search_performed %} + {{ _('Search Results') }} + {% if not search_results %} + {{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }} + {% endif %} + {% endif %} + + {% if search_results %} + + {% for href, caption, context in search_results %} + + {{ caption }} + {{ context|e }} + + {% endfor %} + + {% endif %} + +{% endblock %} diff --git a/doc/_themes/lammps_theme/searchbox.html b/doc/_themes/lammps_theme/searchbox.html new file mode 100644 index 00000000..35ad52c5 --- /dev/null +++ b/doc/_themes/lammps_theme/searchbox.html @@ -0,0 +1,9 @@ +{%- if builder != 'singlehtml' %} + + + + + + + +{%- endif %} diff --git a/doc/_themes/lammps_theme/versions.html b/doc/_themes/lammps_theme/versions.html new file mode 100644 index 00000000..8b3eb79d --- /dev/null +++ b/doc/_themes/lammps_theme/versions.html @@ -0,0 +1,37 @@ +{% if READTHEDOCS %} +{# Add rst-badge after rst-versions for small badge style. #} + + + Read the Docs + v: {{ current_version }} + + + + + Versions + {% for slug, url in versions %} + {{ slug }} + {% endfor %} + + + Downloads + {% for type, url in downloads %} + {{ type }} + {% endfor %} + + + On Read the Docs + + Project Home + + + Builds + + + + Free document hosting provided by Read the Docs. + + + +{% endif %} + diff --git a/etc/bashrc b/etc/bashrc index ac8fda40..d430a61d 100755 --- a/etc/bashrc +++ b/etc/bashrc @@ -17,7 +17,7 @@ #------------------------------------------------------------------------------ export CFDEM_PROJECT=CFDEM -export CFDEM_VERSION=19.02 +export CFDEM_VERSION=19.09 ################################################################################ # USER EDITABLE PART: Changes made here may be lost with the next upgrade diff --git a/etc/cshrc b/etc/cshrc index 5ce854ac..feb0022c 100755 --- a/etc/cshrc +++ b/etc/cshrc @@ -15,7 +15,7 @@ #------------------------------------------------------------------------------ setenv CFDEM_PROJECT CFDEM -setenv CFDEM_VERSION 19.02 +setenv CFDEM_VERSION 19.09 ################################################################################ # USER EDITABLE PART: Changes made here may be lost with the next upgrade diff --git a/etc/library-list.txt b/etc/library-list.txt index 8e14f45d..c27feda1 100644 --- a/etc/library-list.txt +++ b/etc/library-list.txt @@ -1,4 +1,5 @@ lagrangian/cfdemParticle/dir lagrangian/cfdemParticleComp/dir +recurrence/dir finiteVolume/dir ../applications/solvers/cfdemSolverMultiphase/multiphaseMixture/dir diff --git a/etc/solver-list.txt b/etc/solver-list.txt index c370a4d4..1fa07ecc 100644 --- a/etc/solver-list.txt +++ b/etc/solver-list.txt @@ -1,7 +1,12 @@ +rcfdemSolverRhoSteadyPimple/dir +rcfdemSolverHeattransfer/dir +rcfdemSolverCoupledHeattransfer/dir +rStatAnalysis/dir +rcfdemSolverBase/dir +rtfmSolverSpecies/dir cfdemSolverPisoMS/dir cfdemSolverPiso/dir cfdemSolverRhoPimple/dir -cfdemSolverRhoSimple/dir cfdemSolverIB/dir cfdemSolverPisoScalar/dir cfdemSolverRhoPimpleChem/dir diff --git a/etc/utilities-list.txt b/etc/utilities-list.txt index a8ac78bd..8b65188c 100644 --- a/etc/utilities-list.txt +++ b/etc/utilities-list.txt @@ -1 +1,4 @@ cfdemPostproc/dir +rSmoother/dir +rBaseMirror/rBaseMirrorScalar/dir +rBaseMirror/rBaseMirrorVec/dir diff --git a/src/.gitignore b/src/.gitignore index 44599544..ce60e8c7 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -5,3 +5,5 @@ log_* log.* *~ + +lnInclude diff --git a/src/lagrangian/cfdemParticle/Make/files b/src/lagrangian/cfdemParticle/Make/files index 2d409055..08c71bf5 100644 --- a/src/lagrangian/cfdemParticle/Make/files +++ b/src/lagrangian/cfdemParticle/Make/files @@ -1,5 +1,6 @@ cfdemCloud = cfdemCloud cfdTools = cfdTools +recModels = subModels/recModel energyModels = subModels/energyModel forceModels = subModels/forceModel forceSubModels = subModels/forceModel/forceSubModels @@ -40,7 +41,8 @@ $(chemistryModels)/reactantPerParticle/reactantPerParticle.C $(energyModels)/energyModel/energyModel.C $(energyModels)/energyModel/newEnergyModel.C $(energyModels)/heatTransferGunn/heatTransferGunn.C -$(energyModels)/heatTransferGunnPartField/heatTransferGunnPartField.C +$(energyModels)/heatTransferRanzMarshall/heatTransferRanzMarshall.C +$(energyModels)/heatTransferGranConduction/heatTransferGranConduction.C $(energyModels)/reactionHeat/reactionHeat.C $(thermCondModels)/thermCondModel/thermCondModel.C @@ -71,6 +73,12 @@ $(forceModels)/MeiLift/MeiLift.C $(forceModels)/particleCellVolume/particleCellVolume.C $(forceModels)/fieldTimeAverage/fieldTimeAverage.C $(forceModels)/volWeightedAverage/volWeightedAverage.C +$(forceModels)/deactivateForce/deactivateForce.C +$(forceModels)/freeStreaming/freeStreaming.C +$(forceModels)/isotropicFluctuations/isotropicFluctuations.C +$(forceModels)/evaluateFluctuations/evaluateFluctuations.C +$(forceModels)/directedDiffusiveRelaxation/directedDiffusiveRelaxation.C +$(forceModels)/potentialRelaxation/potentialRelaxation.C $(forceModels)/BeetstraDrag/BeetstraDrag.C $(forceModels)/BeetstraDragPoly/BeetstraDragPoly.C $(forceModels)/dSauter/dSauter.C @@ -82,6 +90,7 @@ $(forceModels)/granKineticEnergy/granKineticEnergy.C $(forceModels)/pdCorrelation/pdCorrelation.C $(forceModels)/surfaceTensionForce/surfaceTensionForce.C $(forceModels)/gradPForceSmooth/gradPForceSmooth.C +$(forceModels)/particleDeformation/particleDeformation.C $(forceModelsMS)/forceModelMS/forceModelMS.C $(forceModelsMS)/forceModelMS/newForceModelMS.C @@ -119,6 +128,7 @@ $(voidFractionModels)/dividedVoidFractionMS/dividedVoidFractionMS.C $(voidFractionModels)/bigParticleVoidFraction/bigParticleVoidFraction.C $(voidFractionModels)/GaussVoidFraction/GaussVoidFraction.C $(voidFractionModels)/IBVoidFraction/IBVoidFraction.C +$(voidFractionModels)/noVoidFraction/noVoidFraction.C $(voidFractionModels)/trilinearVoidFraction/trilinearVoidFraction.C $(locateModels)/locateModel/locateModel.C @@ -138,6 +148,7 @@ $(momCoupleModels)/momCoupleModel/newMomCoupleModel.C $(momCoupleModels)/explicitCouple/explicitCouple.C $(momCoupleModels)/implicitCouple/implicitCouple.C $(momCoupleModels)/noCouple/noCouple.C +$(momCoupleModels)/deactivateCouple/deactivateCouple.C $(regionModels)/regionModel/regionModel.C $(regionModels)/regionModel/newRegionModel.C @@ -156,6 +167,7 @@ $(averagingModels)/averagingModel/averagingModel.C $(averagingModels)/averagingModel/newAveragingModel.C $(averagingModels)/dilute/dilute.C $(averagingModels)/dense/dense.C +$(averagingModels)/noAveraging/noAveraging.C $(clockModels)/clockModel/clockModel.C $(clockModels)/clockModel/newClockModel.C diff --git a/src/lagrangian/cfdemParticle/cfdTools/versionInfo.H b/src/lagrangian/cfdemParticle/cfdTools/versionInfo.H index 7297ac62..7fb67161 100755 --- a/src/lagrangian/cfdemParticle/cfdTools/versionInfo.H +++ b/src/lagrangian/cfdemParticle/cfdTools/versionInfo.H @@ -34,12 +34,12 @@ Description #ifndef versionInfo_H #define versionInfo_H -word CFDEMversion="PFM 19.02"; -word compatibleLIGGGHTSversion="PFM 19.02"; +word CFDEMversion="PFM 19.09"; +word compatibleLIGGGHTSversion="PFM 19.09"; word OFversion="4.x"; Info << "\nCFDEMcoupling version: " << CFDEMversion << endl; -Info << ", compatible to LIGGGHTS version: " << compatibleLIGGGHTSversion << endl; -Info << ", compatible to OpenFOAM version: " << OFversion << endl; +Info << "compatible to LIGGGHTS version: " << compatibleLIGGGHTSversion << endl; +Info << "compatible to OpenFOAM version: " << OFversion << endl; #endif diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C index d5c4efab..754f2b23 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.C @@ -45,6 +45,7 @@ Description #include "smoothingModel.H" #include "liggghtsCommandModel.H" #include "otherForceModel.H" +#include "IOmanip.H" namespace Foam { @@ -105,6 +106,8 @@ cfdemCloud::cfdemCloud particleWeights_(NULL), particleVolumes_(NULL), particleV_(NULL), + particleConvVel_(NULL), + particleFlucVel_(NULL), numberOfParticles_(0), d32_(-1), numberOfParticlesChanged_(false), @@ -386,6 +389,8 @@ cfdemCloud::~cfdemCloud() dataExchangeM().destroy(particleWeights_,1); dataExchangeM().destroy(particleVolumes_,1); dataExchangeM().destroy(particleV_,1); + dataExchangeM().destroy(particleConvVel_,3); + dataExchangeM().destroy(particleFlucVel_,3); if(getParticleDensities_) dataExchangeM().destroy(particleDensities_,1); if(getParticleEffVolFactors_) dataExchangeM().destroy(particleEffVolFactors_,1); if(getParticleTypes_) dataExchangeM().destroy(particleTypes_,1); @@ -443,6 +448,8 @@ void cfdemCloud::findCells() void cfdemCloud::setForces() { resetArray(fluidVel_,numberOfParticles(),3); + resetArray(particleConvVel_,numberOfParticles(),3); + resetArray(particleFlucVel_,numberOfParticles(),3); resetArray(impForces_,numberOfParticles(),3); resetArray(expForces_,numberOfParticles(),3); resetArray(DEMForces_,numberOfParticles(),3); @@ -522,7 +529,7 @@ void cfdemCloud::checkCG(bool ok) if(!ok) cgOK_ = ok; } -void cfdemCloud::setPos(double**& pos) +void cfdemCloud::setPos(const double *const * pos) { for(int index = 0; index < numberOfParticles(); ++index) { @@ -555,11 +562,6 @@ vector cfdemCloud::expForce(int index) const return vector(DEMForces()[index][0],DEMForces()[index][1],DEMForces()[index][2]); } -vector cfdemCloud::fluidVel(int index) const -{ - return vector(fluidVels()[index][0],fluidVels()[index][1],fluidVels()[index][2]); -} - const forceModel& cfdemCloud::forceM(int i) { return forceModel_[i]; @@ -665,16 +667,14 @@ bool cfdemCloud::evolve } //============================================ - //CHECK JUST TIME-INTERPOATE ALREADY SMOOTHENED VOIDFRACTIONNEXT AND UsNEXT FIELD + //CHECK JUST TIME-INTERPOLATE ALREADY SMOOTHENED VOIDFRACTIONNEXT AND UsNEXT FIELD // IMPLICIT FORCE CONTRIBUTION AND SOLVER USE EXACTLY THE SAME AVERAGED // QUANTITIES AT THE GRID! - scalar timeStepFrac = dataExchangeM().timeStepFraction(); + const scalar timeStepFrac = dataExchangeM().timeStepFraction(); + int old_precision = Info().precision(10); Info << "\n timeStepFraction() = " << timeStepFrac << endl; - if(timeStepFrac > 1.0000001) - { - // FatalError << "cfdemCloud::dataExchangeM().timeStepFraction()>1: Do not do this, since dangerous. This might be due to the fact that you used a adjustable CFD time step. Please use a fixed CFD time step." << abort(FatalError); - Warning << "cfdemCloud::dataExchangeM().timeStepFraction() = " << timeStepFrac << endl; - } + Info().precision(old_precision); + clockM().start(24,"interpolateEulerFields"); // update voidFractionField @@ -744,6 +744,8 @@ bool cfdemCloud::reAllocArrays() dataExchangeM().allocateArray(velocities_,0.,3); dataExchangeM().allocateArray(fluidVel_,0.,3); dataExchangeM().allocateArray(fAcc_,0.,3); + dataExchangeM().allocateArray(particleConvVel_,0.,3); + dataExchangeM().allocateArray(particleFlucVel_,0.,3); dataExchangeM().allocateArray(impForces_,0.,3); dataExchangeM().allocateArray(expForces_,0.,3); dataExchangeM().allocateArray(DEMForces_,0.,3); diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H index ab0b76fd..94a1e779 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloud.H @@ -106,13 +106,13 @@ protected: const word modelType_; - double **positions_; + double **positions_; // particle positions - double **velocities_; + double **velocities_; // particle velocities - double **fluidVel_; + double **fluidVel_; // fluid velocities at particle positions - double **fAcc_; + double **fAcc_; // accumulated implicit forces on particles (only used in Koch Hill drag model) double **impForces_; @@ -120,25 +120,29 @@ protected: double **DEMForces_; - double **Cds_; + double **Cds_; // Ksl - double **radii_; + double **radii_; // particle radii double **voidfractions_; - int **cellIDs_; + int **cellIDs_; // ID of cell each particle is in - double **particleDensities_; + double **particleDensities_; // particle densities - double **particleEffVolFactors_; + double **particleEffVolFactors_; // per particle volume factor - int **particleTypes_; + int **particleTypes_; // per particle type - double **particleWeights_; + double **particleWeights_; // particle weights - double **particleVolumes_; + double **particleVolumes_; // particle volumes with subcell information - double **particleV_; + double **particleV_; // particle total volumes + + double **particleConvVel_; + + double **particleFlucVel_; int numberOfParticles_; @@ -211,8 +215,6 @@ protected: virtual void giveDEMdata(); - virtual void setNumberOfParticles(int); - virtual void findCells(); virtual void setForces(); @@ -225,11 +227,6 @@ protected: public: - friend class dataExchangeModel; - friend class voidFractionModel; - friend class forceModel; - friend class forceSubModel; - // Constructors //- Construct from mesh and a list of particles @@ -248,9 +245,11 @@ public: void setAllowCFDsubTimestep(bool b) { allowCFDsubTimestep_ = b; } + virtual void setNumberOfParticles(int numberOfParticles); + void checkCG(bool); - void setPos(double **&); + void setPos(const double *const *); const word& modelType() const { return modelType_; } @@ -262,8 +261,6 @@ public: vector expForce(int) const; - vector fluidVel(int) const; - virtual const forceModel& forceM(int); virtual label nrForceModels() const; @@ -324,6 +321,10 @@ public: inline double ** particleWeights() const; + inline double ** particleConvVels() const; + + inline double ** particleFlucVels() const; + virtual inline label body(int) const; virtual inline double particleVolume(int) const; @@ -405,6 +406,12 @@ public: // Write // write cfdemCloud internal data + inline void setPositions(label n,double* pos); + inline void setCellIDs(label n,int* ID); + inline void setCellIDs(DynamicList const& IDs); + inline void setImpDEMdrag(bool flag) { impDEMdrag_ = flag; } + inline void setImpDEMdragAcc(bool flag) { impDEMdragAcc_ = flag; } + virtual bool evolve(volScalarField&,volVectorField&,volVectorField&); virtual void postFlow() {} @@ -412,9 +419,9 @@ public: virtual bool reAllocArrays(); // IO - void writeScalarFieldToTerminal(double**&) const; + void writeScalarFieldToTerminal(const double *const *) const; - void writeVectorFieldToTerminal(double**&) const; + void writeVectorFieldToTerminal(const double *const *) const; // functions tmp divVoidfractionTau(volVectorField& ,volScalarField&) const; diff --git a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H index 504c1682..5c9d426f 100644 --- a/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H +++ b/src/lagrangian/cfdemParticle/cfdemCloud/cfdemCloudI.H @@ -50,6 +50,25 @@ inline void cfdemCloud::setCG(double cg) Info << "cg is set to: " << cg_ << endl; } +inline void cfdemCloud::setPositions(label n,double* pos) +{ + for (int i=0; i const& IDs) +{ + for (int i=0; i +class cfdemCloudRec : public baseCloud +{ +protected: + + void giveDEMdata(); + + void setForces(); + + void setParticleForceField(); + + void setVectorAverages(); + + bool coupleRecFluc_; + + bool coupleRecForce_; + + bool setForceField_; + +public: + + friend class dataExchangeModel; + friend class voidFractionModel; + friend class forceModel; + +// Constructors + + //- Construct from mesh and a list of particles + cfdemCloudRec + ( + const fvMesh& mesh + ); + + //- Destructor + virtual ~cfdemCloudRec(); + +// public Member Functions + + // bool evolve(volScalarField&,volVectorField&,volVectorField&); + +// inline const recModel& recM() const; +// +// void updateRecFields(); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "cfdemCloudRecI.H" + +#endif + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/derived/cfdemCloudRec/cfdemCloudRecI.H b/src/lagrangian/cfdemParticle/derived/cfdemCloudRec/cfdemCloudRecI.H new file mode 100644 index 00000000..eda1d29d --- /dev/null +++ b/src/lagrangian/cfdemParticle/derived/cfdemCloudRec/cfdemCloudRecI.H @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . + +Description + This code is designed to realize coupled rCFD-DEM simulations using LIGGGHTS + and OpenFOAM(R). Note: this code is not part of OpenFOAM(R) (see DISCLAIMER). +\*---------------------------------------------------------------------------*/ + +//#include "cfdemCloudRec.H" +#include "forceModel.H" +namespace Foam +{ + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // +template +cfdemCloudRec::cfdemCloudRec +( + const fvMesh& mesh +) +: + baseCloud(mesh), + coupleRecFluc_(true), + coupleRecForce_(true), + setForceField_(false) +{ + if (baseCloud::couplingProperties().found("coupleRecFluc")) + { + coupleRecFluc_ = readBool(baseCloud::couplingProperties().lookup("coupleRecFluc")); + } + + if (baseCloud::couplingProperties().found("coupleRecForce")) + { + coupleRecForce_ = readBool(baseCloud::couplingProperties().lookup("coupleRecForce")); + } + + if (baseCloud::couplingProperties().found("setForceField")) + { + setForceField_ = readBool(baseCloud::couplingProperties().lookup("setForceField")); + } +} + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * // +template +cfdemCloudRec::~cfdemCloudRec() +{} + +// * * * * * * * * * * * * * * * protected Member Functions * * * * * * * * * * * * * // +template +void cfdemCloudRec::giveDEMdata() +{ + baseCloud::dataExchangeM().giveData("vrec","vector-atom",baseCloud::particleConvVel_); + if(coupleRecFluc_) + { + baseCloud::dataExchangeM().giveData("vfluc","vector-atom",baseCloud::particleFlucVel_); + } + if(coupleRecForce_) + { + baseCloud::dataExchangeM().giveData("dragforce","vector-atom",baseCloud::DEMForces_); + } + if(baseCloud::verbose_) Info << "giveDEMdata done." << endl; +} + +template +void cfdemCloudRec::setForces() +{ + baseCloud::resetArray(baseCloud::particleConvVel_,baseCloud::numberOfParticles(),3); + baseCloud::resetArray(baseCloud::particleFlucVel_,baseCloud::numberOfParticles(),3); + + baseCloud::resetArray(baseCloud::impForces_,baseCloud::numberOfParticles(),3); + baseCloud::resetArray(baseCloud::expForces_,baseCloud::numberOfParticles(),3); + + baseCloud::resetArray(baseCloud::DEMForces_,baseCloud::numberOfParticles(),3); + for (int i=0;i +void cfdemCloudRec::setParticleForceField() +{ + if (setForceField_) + { + baseCloud::setParticleForceField(); + } +} + +template +void cfdemCloudRec::setVectorAverages() +{} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/averagingModel/averagingModel/averagingModel.C b/src/lagrangian/cfdemParticle/subModels/averagingModel/averagingModel/averagingModel.C index b6526912..9494976c 100644 --- a/src/lagrangian/cfdemParticle/subModels/averagingModel/averagingModel/averagingModel.C +++ b/src/lagrangian/cfdemParticle/subModels/averagingModel/averagingModel/averagingModel.C @@ -394,9 +394,9 @@ averagingModel::averagingModel IOobject::READ_IF_PRESENT,//MUST_READ, IOobject::AUTO_WRITE ), - sm.mesh().lookupObject ("Us") - /*sm.mesh(), - dimensionedVector("zero", dimensionSet(0,1,-1,0,0),vector::zero)*/ + // sm.mesh().lookupObject ("Us") + sm.mesh(), + dimensionedVector("zero", dimensionSet(0,1,-1,0,0),vector::zero) ), UsNext_ ( IOobject @@ -407,11 +407,19 @@ averagingModel::averagingModel IOobject::READ_IF_PRESENT,//MUST_READ, IOobject::AUTO_WRITE ), - sm.mesh().lookupObject ("Us") - /*sm.mesh(), - dimensionedVector("zero", dimensionSet(0,1,-1,0,0),vector::zero)*/ + // sm.mesh().lookupObject ("Us") + sm.mesh(), + dimensionedVector("zero", dimensionSet(0,1,-1,0,0),vector::zero) ) -{} +{ + const objectRegistry& db = UsWeightField_.db(); + if (db.foundObject("Us")) + { + const volVectorField& Usref(db.lookupObject("Us")); + UsNext_ = Usref; + UsPrev_ = Usref; + } +} // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // diff --git a/src/lagrangian/cfdemParticle/subModels/averagingModel/noAveraging/noAveraging.C b/src/lagrangian/cfdemParticle/subModels/averagingModel/noAveraging/noAveraging.C new file mode 100644 index 00000000..5f7e48c1 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/averagingModel/noAveraging/noAveraging.C @@ -0,0 +1,95 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger, Gerhard Holzinger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . +\*---------------------------------------------------------------------------*/ + +#include "error.H" + +#include "noAveraging.H" +#include "addToRunTimeSelectionTable.H" +#include "voidFractionModel.H" + +//#include +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(noAveraging, 0); + +addToRunTimeSelectionTable +( + averagingModel, + noAveraging, + dictionary +); + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +noAveraging::noAveraging +( + const dictionary& dict, + cfdemCloud& sm +) +: + averagingModel(dict,sm) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +noAveraging::~noAveraging() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void noAveraging::setScalarAverage +( + volScalarField& field, + double**& value, + double** const& weight, + volScalarField& weightField, + double**const& mask +) const +{} + +void noAveraging::setVectorAverage +( + volVectorField& field, + double**& value, + double** const& weight, + volScalarField& weightField, + double**const& mask +) const +{} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/averagingModel/noAveraging/noAveraging.H b/src/lagrangian/cfdemParticle/subModels/averagingModel/noAveraging/noAveraging.H new file mode 100644 index 00000000..b1ab9ac9 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/averagingModel/noAveraging/noAveraging.H @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger, Gerhard Holzinger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . +\*---------------------------------------------------------------------------*/ + +#ifndef noAveraging_H +#define noAveraging_H + +#include "averagingModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class noDrag Declaration +\*---------------------------------------------------------------------------*/ + +class noAveraging +: + public averagingModel +{ + +public: + + //- Runtime type information + TypeName("off"); + + + // Constructors + + //- Construct from components + noAveraging + ( + const dictionary& dict, + cfdemCloud& sm + ); + + // Destructor + + ~noAveraging(); + + + // Member Functions + void setScalarAverage + ( + volScalarField& field, + double**& value, + double** const& weight, + volScalarField& weightField, + double**const& mask + ) const; + + void setVectorAverage + ( + volVectorField& field, + double**& value, + double** const& weight, + volScalarField& weightField, + double**const& mask + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/chemistryModel/diffusionCoefficients/diffusionCoefficients.C b/src/lagrangian/cfdemParticle/subModels/chemistryModel/diffusionCoefficients/diffusionCoefficients.C index 62695fd1..9ce61c26 100644 --- a/src/lagrangian/cfdemParticle/subModels/chemistryModel/diffusionCoefficients/diffusionCoefficients.C +++ b/src/lagrangian/cfdemParticle/subModels/chemistryModel/diffusionCoefficients/diffusionCoefficients.C @@ -72,24 +72,12 @@ diffusionCoefficient::diffusionCoefficient P_(sm.mesh().lookupObject(pressureFieldName_)), partPressureName_(propsDict_.lookupOrDefault("partPressureName","partP")), partPressure_(NULL), - densityFieldName_(propsDict_.lookupOrDefault("densityFieldName","rho")), - rho_(sm.mesh().lookupObject (densityFieldName_)), - molarConcFieldName_(propsDict_.lookupOrDefault("totalMoleFieldName","molarConc")), - molarConc_(sm.mesh().lookupObject(molarConcFieldName_)), X_(speciesNames_.size()), diffusantGasNames_(propsDict_.lookup("diffusantGasNames")), diffusionCoefficients_(diffusantGasNames_.size(),NULL), + Xdiffusant_(diffusantGasNames_.size()), initialized_(false) { - if(verbose_) - { - Info << " Reading diffusionCoefficient list: " << diffusantGasNames_ << endl; - for (int i = 0; i < diffusantGasNames_.size(); i++) - { - Info << "Diffusant names: " << diffusantGasNames_[i] << endl; - } - } - particleCloud_.checkCG(false); allocateMyArrays(); createCoeffs(); @@ -108,7 +96,8 @@ diffusionCoefficient::~diffusionCoefficient() } // * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // - void diffusionCoefficient::allocateMyArrays() const + +void diffusionCoefficient::allocateMyArrays() const { double initVal=0.0; if (particleCloud_.dataExchangeM().maxNumberOfParticles() > 0) @@ -123,14 +112,11 @@ diffusionCoefficient::~diffusionCoefficient() void diffusionCoefficient::reAllocMyArrays() const { - if (particleCloud_.numberOfParticlesChanged()) + double initVal=0.0; + particleCloud_.dataExchangeM().allocateArray(partPressure_,initVal,1,"nparticles"); + for (int i=0; i (mesh_.lookupObject("X_"+speciesNames_[i])); X_.set(i, &X); - - if(verbose_) - { - Info << " Read species list from: " << specDict_.name() << endl; - Info << " Reading species list: " << speciesNames_ << endl; - Info << " Looking up species fields: " << "X_"+speciesNames_[i] << endl; - Info << "The molar fraction fields (X_i): " << X_[i].name() << nl << endl; - } } + + for (int j = 0; j < diffusantGasNames_.size(); j++) + { + volScalarField& Xdiffusant = const_cast + (mesh_.lookupObject("X_"+diffusantGasNames_[j])); + Xdiffusant_.set(j, &Xdiffusant); + + if (verbose_) + { + Info << " Reading diffusing gas species list: " << diffusantGasNames_ << endl; + Info << " Looking up diffusin gas species fields: " << "X_"+diffusantGasNames_[j] << endl; + Info << " The molar fraction fields (Xdiffusant_i): " << Xdiffusant_[j].name() << nl << endl; + } + } + initialized_ = true; } @@ -168,196 +161,115 @@ void diffusionCoefficient::execute() label cellI=0; scalar Tfluid(0); - scalar rhofluid(0); scalar Pfluid(0); - scalar molarConcfluid(0); scalar Texp(0); scalar dBinary_(0); scalar Xnegative(0); - List Xfluid_(0); - Xfluid_.setSize(speciesNames_.size()); - List XfluidDiffusant_(0); - XfluidDiffusant_.setSize(diffusantGasNames_.size()); - List MixtureBinaryDiffusion_; - MixtureBinaryDiffusion_.setSize(diffusantGasNames_.size()); - List TotalFraction_; - TotalFraction_.setSize(diffusantGasNames_.size()); + List TotalFraction_(diffusantGasNames_.size(),Zero); - // defining interpolators for T, rho, voidfraction, N + // defining interpolators for T and Pressure interpolationCellPoint TInterpolator_(tempField_); - interpolationCellPoint rhoInterpolator_(rho_); interpolationCellPoint PInterpolator_(P_); - interpolationCellPoint molarConcInterpolator_(molarConc_); for (int index=0; index=0) { if(interpolation_) { - vector position = particleCloud_.position(index); - Tfluid = TInterpolator_.interpolate(position,cellI); - rhofluid = rhoInterpolator_.interpolate(position,cellI); - Pfluid = PInterpolator_.interpolate(position,cellI); - molarConcfluid = molarConcInterpolator_.interpolate(position,cellI); + vector position = particleCloud_.position(index); + Tfluid = TInterpolator_.interpolate(position,cellI); + Pfluid = PInterpolator_.interpolate(position,cellI); } else { - Tfluid = tempField_[cellI]; - rhofluid = rho_[cellI]; - Pfluid = P_[cellI]; - molarConcfluid = molarConc_[cellI]; + Tfluid = tempField_[cellI]; + Pfluid = P_[cellI]; - for (int i = 0; i X_; wordList diffusantGasNames_; mutable List diffusionCoefficients_; + UPtrList Xdiffusant_; + HashTable coeffs; HashTable molWeight; diff --git a/src/lagrangian/cfdemParticle/subModels/chemistryModel/massTransferCoeff/massTransferCoeff.C b/src/lagrangian/cfdemParticle/subModels/chemistryModel/massTransferCoeff/massTransferCoeff.C index a3a3194b..2f49a729 100644 --- a/src/lagrangian/cfdemParticle/subModels/chemistryModel/massTransferCoeff/massTransferCoeff.C +++ b/src/lagrangian/cfdemParticle/subModels/chemistryModel/massTransferCoeff/massTransferCoeff.C @@ -69,6 +69,7 @@ massTransferCoeff::massTransferCoeff scaleDia_(1) { particleCloud_.checkCG(true); + allocateMyArrays(); } // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // @@ -95,12 +96,9 @@ void massTransferCoeff::allocateMyArrays() const void massTransferCoeff::reAllocMyArrays() const { - if (particleCloud_.numberOfParticlesChanged()) - { - double initVal=0.0; - particleCloud_.dataExchangeM().allocateArray(partNu_,initVal,1); - particleCloud_.dataExchangeM().allocateArray(partRe_,initVal,1); - } + double initVal=0.0; + particleCloud_.dataExchangeM().allocateArray(partNu_,initVal,1); + particleCloud_.dataExchangeM().allocateArray(partRe_,initVal,1); } // * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // @@ -188,10 +186,10 @@ void massTransferCoeff::execute() partRe_[index][0] = Rep; } - if (verbose_ && index >=0 && index < 2) + if (verbose_) { - Info << "Nufield = " << nuf << endl; - Info << "Rep = " << Rep << endl; + Pout << "Nufield = " << nuf << endl; + Pout << "Rep = " << Rep << endl; } } diff --git a/src/lagrangian/cfdemParticle/subModels/chemistryModel/noChemistry/noChemistry.C b/src/lagrangian/cfdemParticle/subModels/chemistryModel/noChemistry/noChemistry.C index 5e4146d7..0eb04f4b 100644 --- a/src/lagrangian/cfdemParticle/subModels/chemistryModel/noChemistry/noChemistry.C +++ b/src/lagrangian/cfdemParticle/subModels/chemistryModel/noChemistry/noChemistry.C @@ -57,8 +57,64 @@ noChemistry::~noChemistry() // * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // +tmp noChemistry::Smi(label i) const +{ + tmp Smi_ + ( + new volScalarField + ( + IOobject + ( + "smi_", + particleCloud_.mesh().time().timeName(), + particleCloud_.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + particleCloud_.mesh(), + dimensionedScalar + ( + "zero", + dimMass/(dimVol*dimTime), + 0.0 + ) + ) + ); + + return Smi_; +} + +tmp noChemistry::Sm() const +{ + tmp Sm_ + ( + new volScalarField + ( + IOobject + ( + "Sm_", + particleCloud_.mesh().time().timeName(), + particleCloud_.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + particleCloud_.mesh(), + dimensionedScalar + ( + "zero", + dimMass/(dimVol*dimTime), + 0.0 + ) + ) + ); + + return Sm_; +} + void noChemistry::execute() -{} +{ + //do nothing +} // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/lagrangian/cfdemParticle/subModels/chemistryModel/noChemistry/noChemistry.H b/src/lagrangian/cfdemParticle/subModels/chemistryModel/noChemistry/noChemistry.H index 5f0840ab..c4f7b061 100644 --- a/src/lagrangian/cfdemParticle/subModels/chemistryModel/noChemistry/noChemistry.H +++ b/src/lagrangian/cfdemParticle/subModels/chemistryModel/noChemistry/noChemistry.H @@ -66,6 +66,10 @@ public: void execute(); + tmp Smi(const label i) const; + + tmp Sm() const; + }; diff --git a/src/lagrangian/cfdemParticle/subModels/chemistryModel/reactantPerParticle/reactantPerParticle.C b/src/lagrangian/cfdemParticle/subModels/chemistryModel/reactantPerParticle/reactantPerParticle.C index 1573c68a..0d2151c7 100644 --- a/src/lagrangian/cfdemParticle/subModels/chemistryModel/reactantPerParticle/reactantPerParticle.C +++ b/src/lagrangian/cfdemParticle/subModels/chemistryModel/reactantPerParticle/reactantPerParticle.C @@ -56,6 +56,7 @@ reactantPerParticle::reactantPerParticle chemistryModel(dict,sm), propsDict_(dict.subDict(typeName + "Props")), mesh_(sm.mesh()), + verbose_(propsDict_.lookupOrDefault("verbose",false)), reactantPerParticle_(NULL), voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), voidfraction_(sm.mesh().lookupObject(voidfractionFieldName_)), @@ -98,11 +99,8 @@ void reactantPerParticle::allocateMyArrays() const void reactantPerParticle::reAllocMyArrays() const { - if (particleCloud_.numberOfParticlesChanged()) - { - double initVal=0.0; - particleCloud_.dataExchangeM().allocateArray(reactantPerParticle_,initVal,1); - } + double initVal=0.0; + particleCloud_.dataExchangeM().allocateArray(reactantPerParticle_,initVal,1); } // * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // @@ -145,6 +143,8 @@ void reactantPerParticle::execute() particlesPerCell= particlesPerCell_[cellI]; reactantPerParticle_[index][0] = voidfraction * cellvolume / particlesPerCell; } + + if (verbose_) Info << "reactantPerParticle_" << reactantPerParticle_[index][0] << endl; } // give DEM data diff --git a/src/lagrangian/cfdemParticle/subModels/chemistryModel/reactantPerParticle/reactantPerParticle.H b/src/lagrangian/cfdemParticle/subModels/chemistryModel/reactantPerParticle/reactantPerParticle.H index 0fe39037..2e369755 100644 --- a/src/lagrangian/cfdemParticle/subModels/chemistryModel/reactantPerParticle/reactantPerParticle.H +++ b/src/lagrangian/cfdemParticle/subModels/chemistryModel/reactantPerParticle/reactantPerParticle.H @@ -54,6 +54,8 @@ private: const fvMesh& mesh_; + bool verbose_; + mutable double **reactantPerParticle_; word voidfractionFieldName_; diff --git a/src/lagrangian/cfdemParticle/subModels/chemistryModel/species/species.C b/src/lagrangian/cfdemParticle/subModels/chemistryModel/species/species.C index 29493b19..c485a848 100644 --- a/src/lagrangian/cfdemParticle/subModels/chemistryModel/species/species.C +++ b/src/lagrangian/cfdemParticle/subModels/chemistryModel/species/species.C @@ -69,7 +69,7 @@ species::species // create a list from the Species table in the specified species dictionary speciesNames_(specDict_.lookup("species")), mod_spec_names_(speciesNames_.size()), - X_(speciesNames_.size()), //volumeScalarFields + X_(speciesNames_.size()), //volumeScalarFields of molarFractions molarFractions_(speciesNames_.size(),NULL), //the value of molar fractions for every species changeOfSpeciesMass_(speciesNames_.size(),NULL), //the values that are received from DEM with the name of Modified_+species name changeOfSpeciesMassFields_(speciesNames_.size()), //the scalar fields generated with the values from Modified_+species names @@ -125,6 +125,7 @@ species::~species() } // * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // + void species::allocateMyArrays() const { double initVal=0.0; @@ -139,25 +140,21 @@ void species::allocateMyArrays() const { particleCloud_.dataExchangeM().allocateArray(molarFractions_[i],initVal,1,"nparticles"); particleCloud_.dataExchangeM().allocateArray(changeOfSpeciesMass_[i],initVal,1,"nparticles"); - } } } void species::reAllocMyArrays() const { - if (particleCloud_.numberOfParticlesChanged()) - { - double initVal=0.0; - particleCloud_.dataExchangeM().allocateArray(partRho_,initVal,1); - particleCloud_.dataExchangeM().allocateArray(partTemp_,initVal,1); - particleCloud_.dataExchangeM().allocateArray(partMolarConc_,initVal,1); + double initVal=0.0; + particleCloud_.dataExchangeM().allocateArray(partRho_,initVal,1); + particleCloud_.dataExchangeM().allocateArray(partTemp_,initVal,1); + particleCloud_.dataExchangeM().allocateArray(partMolarConc_,initVal,1); - for (int i=0; i Xfluid_; scalar voidfraction(1); - Xfluid_.setSize(speciesNames_.size()); scalar molarConcfluid(0); // defining interpolators for T, rho, voidfraction, molarConc @@ -250,53 +243,49 @@ void species::execute() { if(interpolation_) { - vector position = particleCloud_.position(index); - Tfluid = TInterpolator_.interpolate(position,cellI); - rhofluid = rhoInterpolator_.interpolate(position,cellI); - voidfraction = voidfractionInterpolator_.interpolate(position,cellI); - molarConcfluid = molarConcInterpolator_.interpolate(position,cellI); + vector position = particleCloud_.position(index); + Tfluid = TInterpolator_.interpolate(position,cellI); + rhofluid = rhoInterpolator_.interpolate(position,cellI); + voidfraction = voidfractionInterpolator_.interpolate(position,cellI); + molarConcfluid = molarConcInterpolator_.interpolate(position,cellI); } else { - Tfluid = tempField_[cellI]; - rhofluid = rho_[cellI]; - voidfraction = voidfraction_[cellI]; - molarConcfluid = molarConc_[cellI]; - for (int i = 0; i species::Smi (const label i) const diff --git a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/dataExchangeModel/dataExchangeModel.C b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/dataExchangeModel/dataExchangeModel.C index 723db484..9a1b4a4b 100755 --- a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/dataExchangeModel/dataExchangeModel.C +++ b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/dataExchangeModel/dataExchangeModel.C @@ -43,13 +43,6 @@ defineTypeNameAndDebug(dataExchangeModel, 0); defineRunTimeSelectionTable(dataExchangeModel, dictionary); -// * * * * * * * * * * * * * * protected Member Functions * * * * * * * * * * * * * // - -void dataExchangeModel::setNumberOfParticles(int numberOfParticles) const -{ - particleCloud_.setNumberOfParticles(numberOfParticles); -} - // * * * * * * * * * * * * * * public Member Functions * * * * * * * * * * * * * // //==== @@ -209,7 +202,7 @@ bool dataExchangeModel::couple(int i) scalar dataExchangeModel::timeStepFraction() const { //return fraction between previous coupling TS and actual TS - return ( particleCloud_.mesh().time().value()-particleCloud_.mesh().time().startTime().value() - (couplingStep_-1) * couplingTime() ) / couplingTime(); + return clamp( (particleCloud_.mesh().time().timeIndex() - timeIndexOffset_) * particleCloud_.mesh().time().deltaTValue() / couplingTime() - (couplingStep_ - 1) ); } int dataExchangeModel::getNumberOfParticles() const @@ -249,7 +242,8 @@ dataExchangeModel::dataExchangeModel maxNumberOfParticles_(0), couplingStep_(0), DEMts_(-1.), - couplingInterval_(readScalar(dict_.lookup("couplingInterval"))) + couplingInterval_(readScalar(dict_.lookup("couplingInterval"))), + timeIndexOffset_(particleCloud_.mesh().time().timeIndex()) {} // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // diff --git a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/dataExchangeModel/dataExchangeModel.H b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/dataExchangeModel/dataExchangeModel.H index 672f1138..cf87a4d7 100755 --- a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/dataExchangeModel/dataExchangeModel.H +++ b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/dataExchangeModel/dataExchangeModel.H @@ -68,8 +68,16 @@ protected: int couplingInterval_; + const label timeIndexOffset_; + // Protected member functions + // note: C++17 has std::clamp + scalar clamp(scalar v, scalar lo=0.0, scalar hi=1.0) const + { + return ((v < lo) ? lo : (hi < v) ? hi : v); + } + public: //- Runtime type information @@ -115,7 +123,6 @@ public: // Member Function - void setNumberOfParticles(int) const; inline const int& maxNumberOfParticles() const { return maxNumberOfParticles_; } @@ -186,38 +193,40 @@ public: inline int couplingInterval() const { return couplingInterval_; } - inline scalar couplingTime() const { return couplingInterval_*DEMts_; } + inline scalar couplingTime() const { return couplingInterval_ * DEMts_; } inline scalar TSstart() const { return particleCloud_.mesh().time().startTime().value() + (couplingStep_-1) * couplingTime(); } - inline scalar TSend() const { return particleCloud_.mesh().time().startTime().value() - + (couplingStep_) * couplingTime(); } + inline scalar TSend() const { return particleCloud_.mesh().time().startTime().value() + + (couplingStep_ ) * couplingTime(); } - inline int DEMstepsTillT(scalar t) const { return (t - (particleCloud_.mesh().time().value() - couplingTime()) + SMALL) / DEMts_; } + inline int DEMstepsTillT(scalar t) const { return (t - (particleCloud_.mesh().time().value() - couplingTime()) + SMALL) / DEMts_; } inline void checkTSsize() const { - if (particleCloud_.mesh().time().deltaT().value() > couplingInterval_ * DEMts_ + SMALL) + if (particleCloud_.mesh().time().deltaTValue() > couplingInterval_ * DEMts_ + SMALL) { - Info << "particleCloud_.mesh().time().deltaT().value() = " << particleCloud_.mesh().time().deltaT().value() << endl; + Info << "particleCloud_.mesh().time().deltaTValue() = " << particleCloud_.mesh().time().deltaTValue() << endl; Info << "couplingInterval_ = " << couplingInterval_ << endl; Info << "DEMts_ = " << DEMts_ << endl; FatalError << "\nError - CFD time-step bigger than coupling time (= DEM time step * coupling interval)!\n" << abort(FatalError); } - if (std::fabs((round(couplingTime()/particleCloud_.mesh().time().deltaT().value())*particleCloud_.mesh().time().deltaT().value())-couplingTime()) > SMALL) + + if (std::fabs((round(couplingTime()/particleCloud_.mesh().time().deltaTValue()) * particleCloud_.mesh().time().deltaTValue()) - couplingTime()) > SMALL) { - Info << "particleCloud_.mesh().time().deltaT().value() = " << particleCloud_.mesh().time().deltaT().value() << endl; + Info << "particleCloud_.mesh().time().deltaTValue() = " << particleCloud_.mesh().time().deltaTValue() << endl; Info << "couplingInterval_ = " << couplingInterval_ << endl; Info << "DEMts_ = " << DEMts_ << endl; - Warning << "\nWarning - Coupling time (= DEM time step * coupling interval) is not a multiple of CFD time-step!\n" << endl; + Warning << "\nWarning - Coupling time (= DEM time step * coupling interval) is not a multiple of CFD time-step!\n" << endl; } + if (!particleCloud_.allowCFDsubTimestep()) - if (particleCloud_.mesh().time().deltaT().value() < couplingInterval_ * DEMts_ + SMALL) + if (particleCloud_.mesh().time().deltaTValue() < couplingInterval_ * DEMts_ + SMALL) FatalError << "\nYour models require: CFD time-step = coupling interval (= DEM time step * coupling interval)! \n" << abort(FatalError); // warn if sub-TS - if (particleCloud_.mesh().time().deltaT().value() < couplingTime() - SMALL) + if (particleCloud_.mesh().time().deltaTValue() < couplingTime() - SMALL) Warning << "You are using sub-time-steps (i.e. CFD TS < coupling time)! Check your settings properly." << endl; } @@ -229,15 +238,10 @@ public: inline bool doCoupleNow() const { - if (particleCloud_.mesh().time().value()-particleCloud_.mesh().time().startTime().value()-SMALL - > couplingStep_*DEMts_*couplingInterval_) - { - return true; - } - else - { - return false; - } + return ( (particleCloud_.mesh().time().timeIndex() - timeIndexOffset_) * particleCloud_.mesh().time().deltaTValue() - SMALL + > + couplingStep_ * DEMts_ * couplingInterval_ + ); } virtual int getNumberOfParticles() const; @@ -245,27 +249,6 @@ public: virtual int getNumberOfTypes() const; virtual double* getTypeVol() const; - inline void setPositions(label n,double* pos) - { - for (int i=0;i> just_read; // skip text for dataType // give nr of particles to cloud - setNumberOfParticles(numberOfParticles); + particleCloud_.setNumberOfParticles(numberOfParticles); // re-allocate arrays of cloud particleCloud_.reAllocArrays(); diff --git a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayFiles/twoWayFiles.C b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayFiles/twoWayFiles.C index 7b2238aa..73aed9d6 100644 --- a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayFiles/twoWayFiles.C +++ b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayFiles/twoWayFiles.C @@ -68,7 +68,7 @@ twoWayFiles::twoWayFiles maxNumberOfParticles_ = readScalar(propsDict_.lookup("maxNumberOfParticles")); // give max nr of particles to cloud (corrected later) - setNumberOfParticles(maxNumberOfParticles_); + particleCloud_.setNumberOfParticles(maxNumberOfParticles_); } @@ -134,7 +134,7 @@ void twoWayFiles::getData /*if(name != "outRegion1" && name != "inRegion1")*/ *inputPtr >> numberOfParticles; // give nr of particles to cloud - setNumberOfParticles(numberOfParticles); + particleCloud_.setNumberOfParticles(numberOfParticles); // re-allocate arrays of cloud particleCloud_.reAllocArrays(); diff --git a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMPI/twoWayMPI.C b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMPI/twoWayMPI.C index 875399fa..6f7d0677 100644 --- a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMPI/twoWayMPI.C +++ b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMPI/twoWayMPI.C @@ -29,13 +29,17 @@ Description and OpenFOAM(R). Note: this code is not part of OpenFOAM(R) (see DISCLAIMER). \*---------------------------------------------------------------------------*/ -#include "error.H" #include "twoWayMPI.H" #include "addToRunTimeSelectionTable.H" +#include "OFstream.H" #include "clockModel.H" -#include "pair.h" -#include "force.h" -#include "forceModel.H" +#include "liggghtsCommandModel.H" + +//LAMMPS/LIGGGHTS +#include +#include +#include + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam @@ -66,7 +70,7 @@ twoWayMPI::twoWayMPI propsDict_(dict.subDict(typeName + "Props")), lmp(NULL) { - Info<<"Starting up LIGGGHTS for first time execution"<input->file(liggghtsPath.c_str()); // get DEM time step size @@ -340,7 +344,7 @@ bool twoWayMPI::couple(int i) // give nr of particles to cloud double newNpart = liggghts_get_maxtag(lmp); - setNumberOfParticles(newNpart); + particleCloud_.setNumberOfParticles(newNpart); // re-allocate arrays of cloud particleCloud_.clockM().start(4,"LIGGGHTS_reallocArrays"); diff --git a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMPI/twoWayMPI.H b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMPI/twoWayMPI.H index dd0079e9..9bd66fd5 100644 --- a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMPI/twoWayMPI.H +++ b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMPI/twoWayMPI.H @@ -41,27 +41,15 @@ SourceFiles #ifndef twoWayMPI_H #define twoWayMPI_H +#include + #include "dataExchangeModel.H" -#include "liggghtsCommandModel.H" -#include "OFstream.H" -#include -#include "pair.h" -#include "force.h" -#include "forceModel.H" //=================================// //LAMMPS/LIGGGHTS -#include -#include -#include -#include #include // these are LAMMPS include files -#include -#include -#include -#include -#include -#include +#include +#include //=================================// // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMany2Many/library/Makefile.fedora_fpic b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMany2Many/library/Makefile.fedora_fpic index b2c8df9c..9b399d29 100644 --- a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMany2Many/library/Makefile.fedora_fpic +++ b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMany2Many/library/Makefile.fedora_fpic @@ -6,7 +6,7 @@ SHELL = /bin/sh CC = mpic++ CCFLAGS = -O2 -fPIC \ - -funroll-loops -fstrict-aliasing -Wall -Wextra -Wno-unused-result -Wno-literal-suffix + -funroll-loops -fstrict-aliasing -Wall -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-literal-suffix DEPFLAGS = -M LINK = mpic++ LINKFLAGS = -O -fPIC diff --git a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMany2Many/twoWayMany2Many.C b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMany2Many/twoWayMany2Many.C index 90334d17..79d50ed5 100644 --- a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMany2Many/twoWayMany2Many.C +++ b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayMany2Many/twoWayMany2Many.C @@ -417,7 +417,7 @@ bool twoWayMany2Many::couple(int i) } double newNpart = liggghts_get_maxtag(lmp); - setNumberOfParticles(newNpart); + particleCloud_.setNumberOfParticles(newNpart); if (Npart_ != newNpart) { @@ -430,13 +430,13 @@ bool twoWayMany2Many::couple(int i) firstRun_=false; particleCloud_.clockM().stop("CoupleSyncIDs()"); - setNumberOfParticles(nlocal_foam_); + particleCloud_.setNumberOfParticles(nlocal_foam_); // re-allocate arrays of cloud particleCloud_.reAllocArrays(); - setPositions(nlocal_foam_,pos_foam_); - setCellIDs(nlocal_foam_,cellID_foam_); + particleCloud_.setPositions(nlocal_foam_,pos_foam_); + particleCloud_.setCellIDs(nlocal_foam_,cellID_foam_); Info <<"Foam::twoWayMany2Many::couple(i) done." << endl; } diff --git a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayOne2One/twoWayOne2One.C b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayOne2One/twoWayOne2One.C index d5738c59..0aa2ab91 100644 --- a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayOne2One/twoWayOne2One.C +++ b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayOne2One/twoWayOne2One.C @@ -33,13 +33,19 @@ Contributing authors \*---------------------------------------------------------------------------*/ - #include "twoWayOne2One.H" #include "addToRunTimeSelectionTable.H" +#include "OFstream.H" #include "clockModel.H" -#include "pair.h" -#include "force.h" -#include "forceModel.H" +#include "liggghtsCommandModel.H" + +//LAMMPS/LIGGGHTS +#include +#include +#include +#include +#include +#include // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -82,7 +88,10 @@ twoWayOne2One::twoWayOne2One foam2lig_scl_tmp_(nullptr), staticProcMap_(propsDict_.lookupOrDefault("useStaticProcMap", false)), cellIdComm_(propsDict_.lookupOrDefault("useCellIdComm", false)), + prev_cell_ids_(nullptr), + dbl_cell_ids_(nullptr), my_prev_cell_ids_fix_(nullptr), + boundBoxMargin_(propsDict_.lookupOrDefault("boundingBoxMargin", 0.)), verbose_(propsDict_.lookupOrDefault("verbose", false)), lmp(nullptr) { @@ -120,6 +129,22 @@ twoWayOne2One::twoWayOne2One tmpBoundaryFaces.localPoints() ); thisFoamBox_ = treeBoundBox(boundaryFaces.localPoints()); + if (boundBoxMargin_ > 0.) + { + thisFoamBox_.max() = thisFoamBox_.max() + boundBoxMargin_ * vector::one; + thisFoamBox_.min() = thisFoamBox_.min() - boundBoxMargin_ * vector::one; + + Info<< "twoWayOne2One: Inflating bounding boxes by " + << boundBoxMargin_ << "." + << endl; + } + else if (boundBoxMargin_ < 0.) + { + FatalError + << "twoWayOne2One: Bound box margin cannot be smaller than 0." + << abort(FatalError); + } + if (staticProcMap_) { createProcMap(); @@ -158,6 +183,11 @@ void twoWayOne2One::createProcMap() point(ligbb[0][0], ligbb[0][1], ligbb[0][2]), point(ligbb[1][0], ligbb[1][1], ligbb[1][2]) ); + if (boundBoxMargin_ > 0.) + { + thisLigBox.max() = thisLigBox.max() + boundBoxMargin_ * vector::one; + thisLigBox.min() = thisLigBox.min() - boundBoxMargin_ * vector::one; + } ligBoxes[Pstream::myProcNo()] = thisLigBox; Pstream::gatherList(ligBoxes); Pstream::scatterList(ligBoxes); @@ -209,6 +239,9 @@ twoWayOne2One::~twoWayOne2One() destroy(foam2lig_vec_tmp_); destroy(foam2lig_scl_tmp_); + destroy(prev_cell_ids_); + destroy(dbl_cell_ids_); + delete lmp; } @@ -408,7 +441,7 @@ void twoWayOne2One::allocateArray ) const { int len = max(length,1); - lmp->memory->grow(array, len, width, "o2o:dbl**"); + LAMMPS_MEMORY_NS::grow(array, len, width); for (int i = 0; i < len; i++) for (int j = 0; j < width; j++) array[i][j] = initVal; @@ -423,7 +456,7 @@ void twoWayOne2One::allocateArray ) const { int len = max(particleCloud_.numberOfParticles(),1); - lmp->memory->grow(array, len, width, "o2o:dbl**:autolen"); + LAMMPS_MEMORY_NS::grow(array, len, width); for (int i = 0; i < len; i++) for (int j = 0; j < width; j++) array[i][j] = initVal; @@ -431,7 +464,7 @@ void twoWayOne2One::allocateArray void inline twoWayOne2One::destroy(double** array,int len) const { - lmp->memory->destroy(array); + LAMMPS_MEMORY_NS::destroy(array); } //============ @@ -445,7 +478,7 @@ void twoWayOne2One::allocateArray ) const { int len = max(length,1); - lmp->memory->grow(array, len, width, "o2o:int**"); + LAMMPS_MEMORY_NS::grow(array, len, width); for (int i = 0; i < len; i++) for (int j = 0; j < width; j++) array[i][j] = initVal; @@ -460,7 +493,7 @@ void twoWayOne2One::allocateArray ) const { int len = max(particleCloud_.numberOfParticles(),1); - lmp->memory->grow(array, len, width, "o2o:int**:autolen"); + LAMMPS_MEMORY_NS::grow(array, len, width); for (int i = 0; i < len; i++) for (int j = 0; j < width; j++) array[i][j] = initVal; @@ -468,7 +501,7 @@ void twoWayOne2One::allocateArray void inline twoWayOne2One::destroy(int** array,int len) const { - lmp->memory->destroy(array); + LAMMPS_MEMORY_NS::destroy(array); } //============ @@ -476,14 +509,14 @@ void inline twoWayOne2One::destroy(int** array,int len) const void twoWayOne2One::allocateArray(double*& array, double initVal, int length) const { int len = max(length,1); - lmp->memory->grow(array, len, "o2o:dbl*"); + LAMMPS_MEMORY_NS::grow(array, len); for (int i = 0; i < len; i++) array[i] = initVal; } void inline twoWayOne2One::destroy(double* array) const { - lmp->memory->destroy(array); + LAMMPS_MEMORY_NS::destroy(array); } //============== @@ -491,14 +524,14 @@ void inline twoWayOne2One::destroy(double* array) const void twoWayOne2One::allocateArray(int*& array, int initVal, int length) const { int len = max(length,1); - lmp->memory->grow(array, len, "o2o:int*"); + LAMMPS_MEMORY_NS::grow(array, len); for (int i = 0; i < len; i++) array[i] = initVal; } void inline twoWayOne2One::destroy(int* array) const { - lmp->memory->destroy(array); + LAMMPS_MEMORY_NS::destroy(array); } //============== @@ -646,6 +679,7 @@ bool twoWayOne2One::couple(int i) particleCloud_.clockM().stop("LIGGGHTS"); Info<< "LIGGGHTS finished" << endl; + particleCloud_.clockM().start(4,"One2One_setup"); if (!staticProcMap_) { createProcMap(); @@ -656,6 +690,7 @@ bool twoWayOne2One::couple(int i) locateParticles(); setupFoam2LigCommunication(); + particleCloud_.clockM().stop("One2One_setup"); if (verbose_) { @@ -730,12 +765,11 @@ void twoWayOne2One::locateParticles() destroy(my_flattened_positions); double* my_prev_cell_ids = nullptr; - double* prev_cell_ids = nullptr; if (cellIdComm_) { my_prev_cell_ids = my_prev_cell_ids_fix_->vector_atom; - allocateArray(prev_cell_ids, -1, lig2foam_->ncollected_); - lig2foam_->exchange(my_prev_cell_ids, prev_cell_ids); + allocateArray(prev_cell_ids_, -1, lig2foam_->ncollected_); + lig2foam_->exchange(my_prev_cell_ids, prev_cell_ids_); } if (lig2foam_mask_) @@ -767,7 +801,7 @@ void twoWayOne2One::locateParticles() position, cellIdComm_ ? // don't know whether using round is efficient - (roundedCelli = round(prev_cell_ids[atomi])) < nCells + (roundedCelli = round(prev_cell_ids_[atomi])) < nCells ? roundedCelli : @@ -784,12 +818,8 @@ void twoWayOne2One::locateParticles() cellIds.append(cellI); } } - if (cellIdComm_) - { - destroy(prev_cell_ids); - } - setNumberOfParticles(n_located); + particleCloud_.setNumberOfParticles(n_located); particleCloud_.reAllocArrays(); reduce(n_located, sumOp()); @@ -816,11 +846,11 @@ void twoWayOne2One::locateParticles() extracted_flattened_positions, 3 ); - setPositions(getNumberOfParticles(), extracted_flattened_positions); - destroy(extracted_flattened_positions); + particleCloud_.setPositions(getNumberOfParticles(), extracted_flattened_positions); + delete [] extracted_flattened_positions; destroy(collected_flattened_positions); - setCellIDs(cellIds); + particleCloud_.setCellIDs(cellIds); } void twoWayOne2One::setupFoam2LigCommunication() @@ -871,14 +901,12 @@ void twoWayOne2One::setupFoam2LigCommunication() if (cellIdComm_) { - double** dbl_cell_ids = new double*[getNumberOfParticles()]; + allocateArray(dbl_cell_ids_, -1, 1); for (int atomi = 0; atomi < getNumberOfParticles(); atomi++) - { // TEMPORARY: if this persists after 19.07.2018, call me. - dbl_cell_ids[atomi] = new double[1]; - dbl_cell_ids[atomi][0] = particleCloud_.cellIDs()[atomi][0]; + { + dbl_cell_ids_[atomi][0] = particleCloud_.cellIDs()[atomi][0]; } - giveData("prev_cell_ids", "scalar-atom", dbl_cell_ids, "double"); - delete [] dbl_cell_ids; + giveData("prev_cell_ids", "scalar-atom", dbl_cell_ids_, "double"); } } diff --git a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayOne2One/twoWayOne2One.H b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayOne2One/twoWayOne2One.H index 5414ce4e..9f436b50 100644 --- a/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayOne2One/twoWayOne2One.H +++ b/src/lagrangian/cfdemParticle/subModels/dataExchangeModel/twoWayOne2One/twoWayOne2One.H @@ -45,33 +45,19 @@ Contributing authors #ifndef twoWayOne2One_H #define twoWayOne2One_H +#include + #include "dataExchangeModel.H" -#include "liggghtsCommandModel.H" -#include "OFstream.H" -#include -#include "pair.h" -#include "force.h" -#include "forceModel.H" #include "one2one.H" -#include "meshSearch.H" +#include //=================================// //LAMMPS/LIGGGHTS -#include -#include -#include -#include -#include // these are LAMMPS include files -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include // these are LAMMPS include files +#include +#include +#include /// needed //=================================// // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -115,9 +101,13 @@ private: Switch staticProcMap_; Switch cellIdComm_; + double* prev_cell_ids_; + double** dbl_cell_ids_; LAMMPS_NS::FixPropertyAtom* my_prev_cell_ids_fix_; - treeBoundBox thisFoamBox_; + const scalar boundBoxMargin_; + + treeBoundBox thisFoamBox_; Switch verbose_; diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/energyModel.C b/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/energyModel.C index 6719253b..93d7707b 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/energyModel.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/energyModel.C @@ -81,4 +81,4 @@ scalar energyModel::Cp() const } // End namespace Foam -// ************************************************************************* // +// ************************************************************************* // \ No newline at end of file diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/energyModel.H b/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/energyModel.H index e7c79ded..589f8e50 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/energyModel.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/energyModel.H @@ -109,6 +109,11 @@ public: scalar Cp() const; + virtual scalar aveTpart() const + { + return 0.0; + } + }; diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/newEnergyModel.C b/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/newEnergyModel.C index 67f8c0af..76d10607 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/newEnergyModel.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/energyModel/newEnergyModel.C @@ -64,4 +64,4 @@ autoPtr energyModel::New } // End namespace Foam -// ************************************************************************* // +// ************************************************************************* // \ No newline at end of file diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGranConduction/heatTransferGranConduction.C b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGranConduction/heatTransferGranConduction.C new file mode 100644 index 00000000..135850f7 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGranConduction/heatTransferGranConduction.C @@ -0,0 +1,255 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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 code 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 code. If not, see . + + Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + +\*---------------------------------------------------------------------------*/ + +#include "error.H" +#include "heatTransferGranConduction.H" +#include "addToRunTimeSelectionTable.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(heatTransferGranConduction, 0); + +addToRunTimeSelectionTable(energyModel, heatTransferGranConduction, dictionary); + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +heatTransferGranConduction::heatTransferGranConduction +( + const dictionary& dict, + cfdemCloudEnergy& sm +) +: + energyModel(dict,sm), + propsDict_(dict.subDict(typeName + "Props")), + multiTypes_(false), + verbose_(propsDict_.lookupOrDefault("verbose",false)), + calcTotalHeatFlux_(propsDict_.lookupOrDefault("calcTotalHeatFlux",false)), + totalHeatFlux_(0.0), + QPartPartName_(propsDict_.lookupOrDefault("QPartPartName","QPartPart")), + QPartPart_ + ( IOobject + ( + QPartPartName_, + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) + ), + partEffThermCondField_ + ( + IOobject + ( + "partEffThermCondField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("one", dimensionSet(1, 1, -3, -1,0,0,0), 1.0), + "zeroGradient" + ), + partThermCondField_ + ( + IOobject + ( + "partThermCondField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("one", dimensionSet(1, 1, -3, -1,0,0,0), 1.0), + "zeroGradient" + ), + partTempField_(sm.mesh().lookupObject("partTemp")), + prescribedVoidfractionFieldName_(propsDict_.lookupOrDefault("prescribedVoidfractionFieldName","voidfraction")), + prescribedVoidfraction_(sm.mesh().lookupObject (prescribedVoidfractionFieldName_)), + voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), + voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), + partHeatFluxName_(propsDict_.lookupOrDefault("partHeatFluxName","conductiveHeatFlux")), + partHeatFlux_(NULL), + typePartThermCond_(propsDict_.lookupOrDefault("thermalConductivities",scalarList(1,-1.0))), + partThermCond_(NULL) +{ + allocateMyArrays(); + + if (typePartThermCond_[0] < 0.0) + { + FatalError << "heatTransferGranConduction: provide list of thermal conductivities." << abort(FatalError); + } + + if (typePartThermCond_.size() > 1) + { + multiTypes_ = true; + } + + if (multiTypes_ && !particleCloud_.getParticleTypes()) + { + FatalError << "heatTransferGranConduction needs data for more than one type, but types are not communicated." << abort(FatalError); + } + + if (verbose_) + { + QPartPart_.writeOpt() = IOobject::AUTO_WRITE; + QPartPart_.write(); + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +heatTransferGranConduction::~heatTransferGranConduction() +{ + particleCloud_.dataExchangeM().destroy(partHeatFlux_,1); + particleCloud_.dataExchangeM().destroy(partThermCond_,1); +} + +// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // +void heatTransferGranConduction::allocateMyArrays() const +{ + // get memory for 2d arrays + double initVal=0.0; + particleCloud_.dataExchangeM().allocateArray(partHeatFlux_,initVal,1); + particleCloud_.dataExchangeM().allocateArray(partThermCond_,initVal,1); +} +// * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // + +void heatTransferGranConduction::calcEnergyContribution() +{ + // realloc the arrays + allocateMyArrays(); + + calcPartEffThermCond(); + + QPartPart_ = fvc::laplacian(partEffThermCondField_,partTempField_); + + label cellI=0; + scalar partVolume(0); + scalar QPartPart(0); + scalar voidfraction(1); + + totalHeatFlux_ = 0.0; + + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + cellI = particleCloud_.cellIDs()[index][0]; + if(cellI >= 0) + { + voidfraction = voidfraction_[cellI]; + if (voidfraction < 0.01) + voidfraction = 0.01; + + partVolume = particleCloud_.particleVolume(index); + QPartPart = QPartPart_[cellI]; + + heatFlux(index, partVolume, voidfraction, QPartPart); + if (calcTotalHeatFlux_) totalHeatFlux_ += partHeatFlux_[index][0]; + } + } +} + +void heatTransferGranConduction::calcPartEffThermCond() +{ + calcPartThermCond(); + + scalar volFrac = 0.0; + + forAll(partEffThermCondField_, cellI) + { + volFrac = 1.0 - prescribedVoidfraction_[cellI]; + if (volFrac < 0.334) + { + partEffThermCondField_[cellI] = 0.0; + } + else + { + partEffThermCondField_[cellI] = 0.5 * (3*volFrac - 1) * partThermCondField_[cellI]; + } + } +} + +void heatTransferGranConduction::calcPartThermCond() +{ + label cellI=0; + label partType = 1; + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + cellI = particleCloud_.cellIDs()[index][0]; + if (cellI >= 0) + { + if (multiTypes_) + { + partType = particleCloud_.particleType(index); + } + // LIGGGGHTS counts types 1, 2, ..., C++ array starts at 0 + partThermCond_[index][0] = typePartThermCond_[partType - 1]; + } + } + + partThermCondField_.primitiveFieldRef() = 0.0; + particleCloud_.averagingM().resetWeightFields(); + particleCloud_.averagingM().setScalarAverage + ( + partThermCondField_, + partThermCond_, + particleCloud_.particleWeights(), + particleCloud_.averagingM().UsWeightField(), + NULL + ); +} + +void heatTransferGranConduction::heatFlux(label index, scalar vol, scalar voidfraction, scalar QPartPart) +{ + partHeatFlux_[index][0] = vol * QPartPart / (1.0 - voidfraction) ; +} + +void heatTransferGranConduction::giveData() +{ + if (calcTotalHeatFlux_) + { + reduce(totalHeatFlux_, sumOp()); + Info << "total conductive particle-particle heat flux [W] (Eulerian) = " << totalHeatFlux_ << endl; + } + + particleCloud_.dataExchangeM().giveData(partHeatFluxName_,"scalar-atom", partHeatFlux_); +} + +void heatTransferGranConduction::postFlow() +{ + giveData(); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // + diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGranConduction/heatTransferGranConduction.H b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGranConduction/heatTransferGranConduction.H new file mode 100644 index 00000000..6ab1e180 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGranConduction/heatTransferGranConduction.H @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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 code 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 code. If not, see . + + Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + + Description + heat transfer from granular conduction according to the + Effective Medium Theory discussed e.g. by + Carson et al. Int. J. Heat Mass Transfer 48 (2005) + +\*---------------------------------------------------------------------------*/ + +#ifndef heatTransferGranConduction_H +#define heatTransferGranConduction_H + +#include "fvCFD.H" +#include "cfdemCloudEnergy.H" +#include "energyModel.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class heatTransferGranConduction Declaration +\*---------------------------------------------------------------------------*/ + +class heatTransferGranConduction +: + public energyModel +{ +protected: + + dictionary propsDict_; + + bool multiTypes_; + + bool verbose_; + + bool calcTotalHeatFlux_; + + scalar totalHeatFlux_; + + word QPartPartName_; + + volScalarField QPartPart_; + + volScalarField partEffThermCondField_; + + volScalarField partThermCondField_; + + const volScalarField& partTempField_; + + word prescribedVoidfractionFieldName_; + + const volScalarField& prescribedVoidfraction_; + + word voidfractionFieldName_; + + const volScalarField& voidfraction_; + + word partHeatFluxName_; + + mutable double **partHeatFlux_; + + scalarList typePartThermCond_; + + mutable double **partThermCond_; + + void allocateMyArrays() const; + + void calcPartEffThermCond(); + + void calcPartThermCond(); + + virtual void giveData(); + + virtual void heatFlux(label, scalar, scalar, scalar); + + + +public: + + //- Runtime type information + TypeName("heatTransferGranConduction"); + + // Constructors + + //- Construct from components + heatTransferGranConduction + ( + const dictionary& dict, + cfdemCloudEnergy& sm + ); + + + // Destructor + + virtual ~heatTransferGranConduction(); + + + // Member Functions + + void addEnergyContribution(volScalarField&) const {} + + void addEnergyCoefficient(volScalarField&) const {} + + void calcEnergyContribution(); + + void postFlow(); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // + diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C index f81b2cda..5570b610 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.C @@ -49,6 +49,10 @@ heatTransferGunn::heatTransferGunn interpolation_(propsDict_.lookupOrDefault("interpolation",false)), verbose_(propsDict_.lookupOrDefault("verbose",false)), implicit_(propsDict_.lookupOrDefault("implicit",true)), + calcTotalHeatFlux_(propsDict_.lookupOrDefault("calcTotalHeatFlux",true)), + initPartTemp_(propsDict_.lookupOrDefault("initPartTemp",false)), + totalHeatFlux_(0.0), + NusseltScalingFactor_(1.0), QPartFluidName_(propsDict_.lookupOrDefault("QPartFluidName","QPartFluid")), QPartFluid_ ( IOobject @@ -126,8 +130,7 @@ heatTransferGunn::heatTransferGunn ), partRefTemp_("partRefTemp", dimensionSet(0,0,0,1,0,0,0), 0.0), calcPartTempField_(propsDict_.lookupOrDefault("calcPartTempField",false)), - calcPartTempAve_(propsDict_.lookupOrDefault("calcPartTempAve",false)), - partTempAve_(0.0), + partTempAve_("partTempAve", dimensionSet(0,0,0,1,0,0,0), 0.0), tempFieldName_(propsDict_.lookupOrDefault("tempFieldName","T")), tempField_(sm.mesh().lookupObject (tempFieldName_)), voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), @@ -139,7 +142,7 @@ heatTransferGunn::heatTransferGunn rho_(sm.mesh().lookupObject (densityFieldName_)), partTempName_(propsDict_.lookup("partTempName")), partTemp_(NULL), - partHeatFluxName_(propsDict_.lookup("partHeatFluxName")), + partHeatFluxName_(propsDict_.lookupOrDefault("partHeatFluxName","convectiveHeatFlux")), partHeatFlux_(NULL), partHeatFluxCoeff_(NULL), partRe_(NULL), @@ -149,6 +152,12 @@ heatTransferGunn::heatTransferGunn { allocateMyArrays(); + if (propsDict_.found("NusseltScalingFactor")) + { + NusseltScalingFactor_=readScalar(propsDict_.lookup ("NusseltScalingFactor")); + Info << "NusseltScalingFactor set to: " << NusseltScalingFactor_ << endl; + } + if (propsDict_.found("maxSource")) { maxSource_=readScalar(propsDict_.lookup ("maxSource")); @@ -157,7 +166,6 @@ heatTransferGunn::heatTransferGunn if (calcPartTempField_) { - calcPartTempAve_ = true; if (propsDict_.found("partRefTemp")) { partRefTemp_.value()=readScalar(propsDict_.lookup ("partRefTemp")); @@ -186,6 +194,13 @@ heatTransferGunn::heatTransferGunn } } + if (expNusselt_) + { + NuField_.writeOpt() = IOobject::AUTO_WRITE; + NuField_.write(); + Info << "Using predefined Nusselt number field." << endl; + } + if (propsDict_.found("scale") && typeCG_.size()==1) { // if "scale" is specified and there's only one single type, use "scale" @@ -193,6 +208,11 @@ heatTransferGunn::heatTransferGunn typeCG_[0] = scaleDia_; } else if (typeCG_.size()>1) multiTypes_ = true; + + if (initPartTemp_ && !partTempField_.headerOk()) + { + FatalError <<"Trying to initialize particle temperatures, but no field found.\n" << abort(FatalError); + } } @@ -239,26 +259,17 @@ void heatTransferGunn::calcEnergyContribution() // reset Scalar field QPartFluid_.primitiveFieldRef() = 0.0; - // get DEM data - particleCloud_.dataExchangeM().getData(partTempName_,"scalar-atom",partTemp_); - - if(calcPartTempField_) + if (initPartTemp_) { - partTempField_.primitiveFieldRef() = 0.0; - particleCloud_.averagingM().resetWeightFields(); - particleCloud_.averagingM().setScalarAverage - ( - partTempField_, - partTemp_, - particleCloud_.particleWeights(), - particleCloud_.averagingM().UsWeightField(), - NULL - ); - - volScalarField sumTp (particleCloud_.averagingM().UsWeightField() * partTempField_); - dimensionedScalar aveTemp("aveTemp",dimensionSet(0,0,0,1,0,0,0), gSum(sumTp) / particleCloud_.numberOfParticles()); - partRelTempField_ = (partTempField_ - aveTemp) / (aveTemp - partRefTemp_); - Info << "heatTransferGunn: average part. temp = " << aveTemp.value() << endl; + // if particle temperatures are to be initialized from field, do a one-time push to DEM + initPartTemp(); + particleCloud_.dataExchangeM().giveData("Temp","scalar-atom", partTemp_); + initPartTemp_ = false; + } + else + { + // get DEM data + particleCloud_.dataExchangeM().getData(partTempName_,"scalar-atom",partTemp_); } #ifdef compre @@ -277,7 +288,6 @@ void heatTransferGunn::calcEnergyContribution() Info << "heatTransferGunn using scale from liggghts cg = " << scaleDia_ << endl; } - // calc La based heat flux scalar voidfraction(1); vector Ufluid(0,0,0); scalar Tfluid(0); @@ -292,6 +302,7 @@ void heatTransferGunn::calcEnergyContribution() scalar Pr(0); scalar Nup(0); scalar Tsum(0.0); + scalar Nsum(0.0); scalar cg = typeCG_[0]; label partType = 1; @@ -300,6 +311,8 @@ void heatTransferGunn::calcEnergyContribution() interpolationCellPoint UInterpolator_(U_); interpolationCellPoint TInterpolator_(tempField_); + totalHeatFlux_ = 0.0; + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) { cellI = particleCloud_.cellIDs()[index][0]; @@ -329,23 +342,38 @@ void heatTransferGunn::calcEnergyContribution() scaleDia3 = cg*cg*cg; } - // calc relative velocity - Us = particleCloud_.velocity(index); - magUr = mag(Ufluid - Us); ds = 2.*particleCloud_.radius(index); ds_scaled = ds/cg; - muf = mufField[cellI]; - Rep = ds_scaled * magUr * voidfraction * rho_[cellI]/ muf; - Pr = max(SMALL, Cp_ * muf / kf0_); - Nup = Nusselt(voidfraction, Rep, Pr); + if (expNusselt_) + { + Nup = NuField_[cellI]; + if (Nup < 2.0) + Nup = 2.0; + } + else + { + Us = particleCloud_.velocity(index); + magUr = mag(Ufluid - Us); + muf = mufField[cellI]; + Rep = ds_scaled * magUr * voidfraction * rho_[cellI]/ muf; + Pr = max(SMALL, Cp_ * muf / kf0_); + Nup = Nusselt(voidfraction, Rep, Pr); + } + Nup *= NusseltScalingFactor_; Tsum += partTemp_[index][0]; + Nsum += 1.0; + scalar h = kf0_ * Nup / ds_scaled; scalar As = ds_scaled * ds_scaled * M_PI; // surface area of sphere // calc convective heat flux [W] heatFlux(index, h, As, Tfluid, scaleDia3); + if (calcTotalHeatFlux_ & !implicit_) + { + totalHeatFlux_ += partHeatFlux_[index][0]; + } if(verbose_) { @@ -353,32 +381,36 @@ void heatTransferGunn::calcEnergyContribution() partNu_[index][0] = Nup; } - if(particleCloud_.verbose() && index >=0 && index <2) + if(verbose_ && index >=0 && index <2) { - Info << "partHeatFlux = " << partHeatFlux_[index][0] << endl; - Info << "magUr = " << magUr << endl; - Info << "As = " << As << endl; - Info << "muf = " << muf << endl; - Info << "Rep = " << Rep << endl; - Info << "Pr = " << Pr << endl; - Info << "Nup = " << Nup << endl; - Info << "voidfraction = " << voidfraction << endl; - Info << "partTemp_[index][0] = " << partTemp_[index][0] << endl; - Info << "Tfluid = " << Tfluid << endl ; + Pout << "partHeatFlux = " << partHeatFlux_[index][0] << endl; + Pout << "magUr = " << magUr << endl; + Pout << "kf0 = " << kf0_ << endl; + Pout << "Cp = " << Cp_ << endl; + Pout << "rho = " << rho_[cellI] << endl; + Pout << "h = " << h << endl; + Pout << "ds = " << ds << endl; + Pout << "ds_scaled = " << ds_scaled << endl; + Pout << "As = " << As << endl; + Pout << "muf = " << muf << endl; + Pout << "Rep = " << Rep << endl; + Pout << "Pr = " << Pr << endl; + Pout << "Nup = " << Nup << endl; + Pout << "voidfraction = " << voidfraction << endl; + Pout << "partTemp_[index][0] = " << partTemp_[index][0] << endl; + Pout << "Tfluid = " << Tfluid << endl ; } } } - // gather particle temperature sums and obtain average - if(calcPartTempAve_) + if(calcPartTempField_) { reduce(Tsum, sumOp()); - partTempAve_ = Tsum / particleCloud_.numberOfParticles(); - Info << "mean particle temperature = " << partTempAve_ << endl; + reduce(Nsum, sumOp()); + partTempAve_.value() = Tsum / Nsum; + partTempField(); } - if(calcPartTempField_) partTempField(); - particleCloud_.averagingM().setScalarSum ( QPartFluid_, @@ -426,6 +458,9 @@ void heatTransferGunn::calcEnergyContribution() particleCloud_.averagingM().UsWeightField(), NULL ); + + Info << "Minimum particle temperature: " << gMin(partTempField_) << endl; + Info << "Maximum particle temperature: " << gMax(partTempField_) << endl; } // limit source term in explicit treatment @@ -451,11 +486,11 @@ void heatTransferGunn::addEnergyContribution(volScalarField& Qsource) const Qsource += QPartFluid_; } -void heatTransferGunn::addEnergyCoefficient(volScalarField& Qsource) const +void heatTransferGunn::addEnergyCoefficient(volScalarField& Qcoeff) const { if(implicit_) { - Qsource += QPartFluidCoeff_; + Qcoeff += QPartFluidCoeff_; } } @@ -490,8 +525,12 @@ void heatTransferGunn::heatFlux(label index, scalar h, scalar As, scalar Tfluid, void heatTransferGunn::giveData() { - Info << "total convective particle-fluid heat flux [W] (Eulerian) = " << gSum(QPartFluid_*1.0*QPartFluid_.mesh().V()) << endl; - + // Info << "total convective particle-fluid heat flux [W] (Eulerian) = " << gSum(QPartFluid_*1.0*QPartFluid_.mesh().V()) << endl; + if (calcTotalHeatFlux_) + { + reduce(totalHeatFlux_, sumOp()); + Info << "total convective particle-fluid heat flux [W] = " << totalHeatFlux_ << endl; + } particleCloud_.dataExchangeM().giveData(partHeatFluxName_,"scalar-atom", partHeatFlux_); } @@ -504,6 +543,8 @@ void heatTransferGunn::postFlow() scalar Tpart(0.0); interpolationCellPoint TInterpolator_(tempField_); + totalHeatFlux_ = 0.0; + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) { cellI = particleCloud_.cellIDs()[index][0]; @@ -521,16 +562,16 @@ void heatTransferGunn::postFlow() Tpart = partTemp_[index][0]; partHeatFlux_[index][0] = (Tfluid - Tpart) * partHeatFluxCoeff_[index][0]; + if (calcTotalHeatFlux_) + { + totalHeatFlux_ += partHeatFlux_[index][0]; + } } } } giveData(); } -scalar heatTransferGunn::aveTpart() const -{ - return partTempAve_; -} void heatTransferGunn::partTempField() { @@ -545,8 +586,24 @@ void heatTransferGunn::partTempField() NULL ); - dimensionedScalar aveTemp("aveTemp",dimensionSet(0,0,0,1,0,0,0), partTempAve_); - partRelTempField_ = (partTempField_ - aveTemp) / (aveTemp - partRefTemp_); + dimensionedScalar denom = partTempAve_ - partRefTemp_; + if (denom.value() < SMALL && denom.value() > -SMALL) denom.value() = SMALL; + partRelTempField_ = (partTempField_ - partTempAve_) / denom; + + Info << "heatTransferGunn: average part. temp = " << partTempAve_.value() << endl; +} + +void heatTransferGunn::initPartTemp() +{ + label cellI = 0; + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + cellI = particleCloud_.cellIDs()[index][0]; + if(cellI >= 0) + { + partTemp_[index][0] = partTempField_[cellI]; + } + } } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.H b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.H index 3a03a480..f9aa8e80 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunn/heatTransferGunn.H @@ -56,6 +56,14 @@ protected: bool implicit_; + bool calcTotalHeatFlux_; + + bool initPartTemp_; + + scalar totalHeatFlux_; + + scalar NusseltScalingFactor_; + word QPartFluidName_; volScalarField QPartFluid_; @@ -76,9 +84,7 @@ protected: bool calcPartTempField_; - bool calcPartTempAve_; - - scalar partTempAve_; + dimensionedScalar partTempAve_; word tempFieldName_; @@ -126,6 +132,8 @@ protected: virtual void heatFlux(label, scalar, scalar, scalar, scalar cg3 = 1.0); + virtual void initPartTemp(); + public: //- Runtime type information @@ -155,8 +163,6 @@ public: void calcEnergyContribution(); void postFlow(); - - scalar aveTpart() const; }; diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.C b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.C deleted file mode 100644 index 4835da80..00000000 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferGunnPartField/heatTransferGunnPartField.C +++ /dev/null @@ -1,244 +0,0 @@ -/*---------------------------------------------------------------------------*\ -License - - This 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 code 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 code. If not, see . - - Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria - -\*---------------------------------------------------------------------------*/ - -#include "error.H" -#include "heatTransferGunnPartField.H" -#include "addToRunTimeSelectionTable.H" -#include "thermCondModel.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // - -defineTypeNameAndDebug(heatTransferGunnPartField, 0); - -addToRunTimeSelectionTable(energyModel, heatTransferGunnPartField, dictionary); - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -// Construct from components -heatTransferGunnPartField::heatTransferGunnPartField -( - const dictionary& dict, - cfdemCloudEnergy& sm -) -: - heatTransferGunn(dict,sm), - partCpField_ - ( - IOobject - ( - "partCp", - sm.mesh().time().timeName(), - sm.mesh(), - IOobject::READ_IF_PRESENT, - IOobject::NO_WRITE - ), - sm.mesh(), - dimensionedScalar("zero", dimensionSet(0,2,-2,-1,0,0,0), 0.0), - "zeroGradient" - ), - partRhoField_(sm.mesh().lookupObject("partRho")), - typeCp_(propsDict_.lookupOrDefault("specificHeatCapacities",scalarList(1,-1.0))), - partCp_(NULL), - pTMax_(dimensionedScalar("pTMax",dimensionSet(0,0,0,1,0,0,0), -1.0)), - pTMin_(dimensionedScalar("pTMin",dimensionSet(0,0,0,1,0,0,0), -1.0)), - thermCondModel_ - ( - thermCondModel::New - ( - propsDict_, - sm - ) - ), - fvOptions(fv::options::New(sm.mesh())) -{ - if (!implicit_) - { - FatalError << "heatTransferGunnPartField requires implicit heat transfer treatment." << abort(FatalError); - } - - if (typeCp_[0] < 0.0) - { - FatalError << "heatTransferGunnPartField: provide list of specific heat capacities." << abort(FatalError); - } - - if (propsDict_.found("pTMax")) - { - pTMax_.value()=scalar(readScalar(propsDict_.lookup("pTMax"))); - } - - if (propsDict_.found("pTMin")) - { - pTMin_.value()=scalar(readScalar(propsDict_.lookup("pTMin"))); - } - - partTempField_.writeOpt() = IOobject::AUTO_WRITE; - - allocateMyArrays(); -} - - -// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - -heatTransferGunnPartField::~heatTransferGunnPartField() -{ - particleCloud_.dataExchangeM().destroy(partCp_,1); -} - -// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // - -void heatTransferGunnPartField::allocateMyArrays() const -{ - double initVal=0.0; - particleCloud_.dataExchangeM().allocateArray(partCp_,initVal,1); -} -// * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // -void heatTransferGunnPartField::calcEnergyContribution() -{ - allocateMyArrays(); - heatTransferGunn::calcEnergyContribution(); - - // if heat sources in particles present, pull them here - - // loop over all particles to fill partCp_ based on type - label cellI=0; - label partType = 0; - for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) - { - cellI = particleCloud_.cellIDs()[index][0]; - if(cellI >= 0) - { - partType = particleCloud_.particleType(index); - // LIGGGGHTS counts types 1, 2, ..., C++ array starts at 0 - partCp_[index][0] = typeCp_[partType - 1]; - } - } - - partCpField_.primitiveFieldRef() = 0.0; - particleCloud_.averagingM().resetWeightFields(); - particleCloud_.averagingM().setScalarAverage - ( - partCpField_, - partCp_, - particleCloud_.particleWeights(), - particleCloud_.averagingM().UsWeightField(), - NULL - ); - -} - -void heatTransferGunnPartField::addEnergyContribution(volScalarField& Qsource) const -{ - Qsource -= QPartFluidCoeff_*partTempField_; -} - -void heatTransferGunnPartField::giveData() -{ - particleCloud_.dataExchangeM().giveData(partTempName_,"scalar-atom", partTemp_); -} - -void heatTransferGunnPartField::postFlow() -{ - label cellI; - scalar Tpart(0.0); - interpolationCellPoint partTInterpolator_(partTempField_); - - particleCloud_.dataExchangeM().allocateArray(partTemp_,0.0,1); - - for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) - { - cellI = particleCloud_.cellIDs()[index][0]; - if(cellI >= 0) - { - if(interpolation_) - { - vector position = particleCloud_.position(index); - Tpart = partTInterpolator_.interpolate(position,cellI); - } - else - { - Tpart = partTempField_[cellI]; - } - partTemp_[index][0] = Tpart; - } - } - - giveData(); -} - -void heatTransferGunnPartField::solve() -{ - // for some weird reason, the particle-fluid heat transfer fields were defined with a negative sign - - volScalarField alphaP = 1.0 - voidfraction_; - volScalarField correctedQPartFluidCoeff(QPartFluidCoeff_); - // no heattransfer in empty cells -- for numerical stability, add small amount - forAll(correctedQPartFluidCoeff,cellI) - { - if (-correctedQPartFluidCoeff[cellI] < SMALL) correctedQPartFluidCoeff[cellI] = -SMALL; - } - - volScalarField Qsource = correctedQPartFluidCoeff*tempField_; - volScalarField partCpEff = alphaP*partRhoField_*partCpField_; - volScalarField thCondEff = alphaP*thermCondModel_().thermCond(); -// thCondEff.correctBoundaryConditions(); - - - - fvScalarMatrix partTEqn - ( - // fvm::ddt(partCpEff, partTempField_) - // + Qsource - Qsource - - fvm::Sp(correctedQPartFluidCoeff, partTempField_) - - fvm::laplacian(thCondEff,partTempField_) - == - fvOptions(partCpEff, partTempField_) - ); - // if transient add time derivative - need particle density and specific heat fields - // if sources activated add sources - // if convection activated add convection - - partTEqn.relax(); - - fvOptions.constrain(partTEqn); - - partTEqn.solve(); - - partTempField_.relax(); - - fvOptions.correct(partTempField_); - - if (pTMax_.value() > 0.0) partTempField_ = min(partTempField_, pTMax_); - if (pTMin_.value() > 0.0) partTempField_ = max(partTempField_, pTMin_); - - - Info<< "partT max/min : " << max(partTempField_).value() << " " << min(partTempField_).value() << endl; - -} -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferRanzMarshall/heatTransferRanzMarshall.C b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferRanzMarshall/heatTransferRanzMarshall.C new file mode 100644 index 00000000..44671c00 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferRanzMarshall/heatTransferRanzMarshall.C @@ -0,0 +1,601 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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 code 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 code. If not, see . + + Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + +\*---------------------------------------------------------------------------*/ + +#include "error.H" +#include "heatTransferRanzMarshall.H" +#include "addToRunTimeSelectionTable.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(heatTransferRanzMarshall, 0); + +addToRunTimeSelectionTable(energyModel, heatTransferRanzMarshall, dictionary); + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +heatTransferRanzMarshall::heatTransferRanzMarshall +( + const dictionary& dict, + cfdemCloudEnergy& sm +) +: + energyModel(dict,sm), + propsDict_(dict.subDict(typeName + "Props")), + multiTypes_(false), + expNusselt_(propsDict_.lookupOrDefault("expNusselt",false)), + interpolation_(propsDict_.lookupOrDefault("interpolation",false)), + verbose_(propsDict_.lookupOrDefault("verbose",false)), + implicit_(propsDict_.lookupOrDefault("implicit",true)), + calcTotalHeatFlux_(propsDict_.lookupOrDefault("calcTotalHeatFlux",true)), + initPartTemp_(propsDict_.lookupOrDefault("initPartTemp",false)), + totalHeatFlux_(0.0), + NusseltScalingFactor_(1.0), + QPartFluidName_(propsDict_.lookupOrDefault("QPartFluidName","QPartFluid")), + QPartFluid_ + ( IOobject + ( + QPartFluidName_, + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0) + ), + QPartFluidCoeffName_(propsDict_.lookupOrDefault("QPartFluidCoeffName","QPartFluidCoeff")), + QPartFluidCoeff_ + ( IOobject + ( + QPartFluidCoeffName_, + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(1,-1,-3,-1,0,0,0), 0.0) + ), + partTempField_ + ( IOobject + ( + "partTemp", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,0,0,1,0,0,0), 0.0), + "zeroGradient" + ), + partRelTempField_ + ( IOobject + ( + "particleRelTemp", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) + ), + ReField_ + ( IOobject + ( + "ReField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) + ), + NuField_ + ( IOobject + ( + "NuField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0) + ), + partRefTemp_("partRefTemp", dimensionSet(0,0,0,1,0,0,0), 0.0), + calcPartTempField_(propsDict_.lookupOrDefault("calcPartTempField",false)), + partTempAve_("partTempAve", dimensionSet(0,0,0,1,0,0,0), 0.0), + tempFieldName_(propsDict_.lookupOrDefault("tempFieldName","T")), + tempField_(sm.mesh().lookupObject (tempFieldName_)), + voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), + voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), + maxSource_(1e30), + velFieldName_(propsDict_.lookupOrDefault("velFieldName","U")), + U_(sm.mesh().lookupObject (velFieldName_)), + densityFieldName_(propsDict_.lookupOrDefault("densityFieldName","rho")), + rho_(sm.mesh().lookupObject (densityFieldName_)), + partTempName_(propsDict_.lookup("partTempName")), + partTemp_(NULL), + partHeatFluxName_(propsDict_.lookupOrDefault("partHeatFluxName","convectiveHeatFlux")), + partHeatFlux_(NULL), + partHeatFluxCoeff_(NULL), + partRe_(NULL), + partNu_(NULL), + scaleDia_(1.), + typeCG_(propsDict_.lookupOrDefault("coarseGrainingFactors",scalarList(1,1.0))) +{ + allocateMyArrays(); + + if (propsDict_.found("NusseltScalingFactor")) + { + NusseltScalingFactor_=readScalar(propsDict_.lookup ("NusseltScalingFactor")); + Info << "NusseltScalingFactor set to: " << NusseltScalingFactor_ << endl; + } + + if (propsDict_.found("maxSource")) + { + maxSource_=readScalar(propsDict_.lookup ("maxSource")); + Info << "limiting eulerian source field to: " << maxSource_ << endl; + } + + if (calcPartTempField_) + { + if (propsDict_.found("partRefTemp")) + { + partRefTemp_.value()=readScalar(propsDict_.lookup ("partRefTemp")); + } + partTempField_.writeOpt() = IOobject::AUTO_WRITE; + partRelTempField_.writeOpt() = IOobject::AUTO_WRITE; + partTempField_.write(); + partRelTempField_.write(); + Info << "Particle temperature field activated." << endl; + } + + if (!implicit_) + { + QPartFluidCoeff_.writeOpt() = IOobject::NO_WRITE; + } + + if (verbose_) + { + ReField_.writeOpt() = IOobject::AUTO_WRITE; + NuField_.writeOpt() = IOobject::AUTO_WRITE; + ReField_.write(); + NuField_.write(); + if (expNusselt_) + { + FatalError <<"Cannot read and create NuField at the same time!\n" << abort(FatalError); + } + } + + if (expNusselt_) + { + NuField_.writeOpt() = IOobject::AUTO_WRITE; + NuField_.write(); + Info << "Using predefined Nusselt number field." << endl; + } + + if (propsDict_.found("scale") && typeCG_.size()==1) + { + // if "scale" is specified and there's only one single type, use "scale" + scaleDia_=scalar(readScalar(propsDict_.lookup("scale"))); + typeCG_[0] = scaleDia_; + } + else if (typeCG_.size()>1) multiTypes_ = true; + + if (initPartTemp_ && !partTempField_.headerOk()) + { + FatalError <<"Trying to initialize particle temperatures, but no field found.\n" << abort(FatalError); + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +heatTransferRanzMarshall::~heatTransferRanzMarshall() +{ + particleCloud_.dataExchangeM().destroy(partTemp_,1); + particleCloud_.dataExchangeM().destroy(partHeatFlux_,1); + particleCloud_.dataExchangeM().destroy(partRe_,1); + particleCloud_.dataExchangeM().destroy(partNu_,1); + if (implicit_) + { + particleCloud_.dataExchangeM().destroy(partHeatFluxCoeff_,1); + } +} + +// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // +void heatTransferRanzMarshall::allocateMyArrays() const +{ + // get memory for 2d arrays + double initVal=0.0; + particleCloud_.dataExchangeM().allocateArray(partTemp_,initVal,1); // field/initVal/with/lenghtFromLigghts + particleCloud_.dataExchangeM().allocateArray(partHeatFlux_,initVal,1); + if(implicit_) + { + particleCloud_.dataExchangeM().allocateArray(partHeatFluxCoeff_,initVal,1); + } + + if(verbose_) + { + particleCloud_.dataExchangeM().allocateArray(partRe_,initVal,1); + particleCloud_.dataExchangeM().allocateArray(partNu_,initVal,1); + } +} + +// * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * // + +void heatTransferRanzMarshall::calcEnergyContribution() +{ + // realloc the arrays + allocateMyArrays(); + + // reset Scalar field + QPartFluid_.primitiveFieldRef() = 0.0; + + if (initPartTemp_) + { + // if particle temperatures are to be initialized from field, do a one-time push to DEM + initPartTemp(); + particleCloud_.dataExchangeM().giveData("Temp","scalar-atom", partTemp_); + initPartTemp_ = false; + } + else + { + // get DEM data + particleCloud_.dataExchangeM().getData(partTempName_,"scalar-atom",partTemp_); + } + + #ifdef compre + const volScalarField mufField = particleCloud_.turbulence().mu(); + #else + const volScalarField mufField = particleCloud_.turbulence().nu()*rho_; + #endif + + if (typeCG_.size()>1 || typeCG_[0] > 1) + { + Info << "heatTransferRanzMarshall using scale = " << typeCG_ << endl; + } + else if (particleCloud_.cg() > 1) + { + scaleDia_=particleCloud_.cg(); + Info << "heatTransferRanzMarshall using scale from liggghts cg = " << scaleDia_ << endl; + } + + // calc La based heat flux + scalar voidfraction(1); + vector Ufluid(0,0,0); + scalar Tfluid(0); + label cellI=0; + vector Us(0,0,0); + scalar ds(0); + scalar ds_scaled(0); + scalar scaleDia3 = typeCG_[0]*typeCG_[0]*typeCG_[0]; + scalar muf(0); + scalar magUr(0); + scalar Rep(0); + scalar Pr(0); + scalar Nup(0); + scalar Tsum(0.0); + scalar Nsum(0.0); + + scalar cg = typeCG_[0]; + label partType = 1; + + interpolationCellPoint voidfractionInterpolator_(voidfraction_); + interpolationCellPoint UInterpolator_(U_); + interpolationCellPoint TInterpolator_(tempField_); + + totalHeatFlux_ = 0.0; + + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + cellI = particleCloud_.cellIDs()[index][0]; + if(cellI >= 0) + { + if(interpolation_) + { + vector position = particleCloud_.position(index); + voidfraction = voidfractionInterpolator_.interpolate(position,cellI); + Ufluid = UInterpolator_.interpolate(position,cellI); + Tfluid = TInterpolator_.interpolate(position,cellI); + } + else + { + voidfraction = voidfraction_[cellI]; + Ufluid = U_[cellI]; + Tfluid = tempField_[cellI]; + } + + if (voidfraction < 0.01) + voidfraction = 0.01; + + if (multiTypes_) + { + partType = particleCloud_.particleType(index); + cg = typeCG_[partType - 1]; + scaleDia3 = cg*cg*cg; + } + + ds = 2.*particleCloud_.radius(index); + ds_scaled = ds/cg; + + if (expNusselt_) + { + Nup = NuField_[cellI]; + if (Nup < 2.0) + Nup = 2.0; + } + else + { + Us = particleCloud_.velocity(index); + magUr = mag(Ufluid - Us); + muf = mufField[cellI]; + Rep = ds_scaled * magUr * voidfraction * rho_[cellI]/ muf; + Pr = max(SMALL, Cp_ * muf / kf0_); + Nup = Nusselt(voidfraction, Rep, Pr); + } + Nup *= NusseltScalingFactor_; + + Tsum += partTemp_[index][0]; + Nsum += 1.0; + + scalar h = kf0_ * Nup / ds_scaled; + scalar As = ds_scaled * ds_scaled * M_PI; // surface area of sphere + + // calc convective heat flux [W] + heatFlux(index, h, As, Tfluid, scaleDia3); + if (calcTotalHeatFlux_ & !implicit_) + { + totalHeatFlux_ += partHeatFlux_[index][0]; + } + + if(verbose_) + { + partRe_[index][0] = Rep; + partNu_[index][0] = Nup; + } + + if(particleCloud_.verbose() && index >=0 && index <2) + { + Info << "partHeatFlux = " << partHeatFlux_[index][0] << endl; + Info << "magUr = " << magUr << endl; + Info << "As = " << As << endl; + Info << "muf = " << muf << endl; + Info << "Rep = " << Rep << endl; + Info << "Pr = " << Pr << endl; + Info << "Nup = " << Nup << endl; + Info << "voidfraction = " << voidfraction << endl; + Info << "partTemp_[index][0] = " << partTemp_[index][0] << endl; + Info << "Tfluid = " << Tfluid << endl ; + } + } + } + + if(calcPartTempField_) + { + reduce(Tsum, sumOp()); + reduce(Nsum, sumOp()); + partTempAve_.value() = Tsum / Nsum; + partTempField(); + } + + particleCloud_.averagingM().setScalarSum + ( + QPartFluid_, + partHeatFlux_, + particleCloud_.particleWeights(), + NULL + ); + + QPartFluid_.primitiveFieldRef() /= -QPartFluid_.mesh().V(); + + if(implicit_) + { + QPartFluidCoeff_.primitiveFieldRef() = 0.0; + + particleCloud_.averagingM().setScalarSum + ( + QPartFluidCoeff_, + partHeatFluxCoeff_, + particleCloud_.particleWeights(), + NULL + ); + + QPartFluidCoeff_.primitiveFieldRef() /= -QPartFluidCoeff_.mesh().V(); + } + + if(verbose_) + { + ReField_.primitiveFieldRef() = 0.0; + NuField_.primitiveFieldRef() = 0.0; + particleCloud_.averagingM().resetWeightFields(); + particleCloud_.averagingM().setScalarAverage + ( + ReField_, + partRe_, + particleCloud_.particleWeights(), + particleCloud_.averagingM().UsWeightField(), + NULL + ); + particleCloud_.averagingM().resetWeightFields(); + particleCloud_.averagingM().setScalarAverage + ( + NuField_, + partNu_, + particleCloud_.particleWeights(), + particleCloud_.averagingM().UsWeightField(), + NULL + ); + } + + // limit source term in explicit treatment + if(!implicit_) + { + forAll(QPartFluid_,cellI) + { + scalar EuFieldInCell = QPartFluid_[cellI]; + + if(mag(EuFieldInCell) > maxSource_ ) + { + Pout << "limiting source term\n" << endl ; + QPartFluid_[cellI] = sign(EuFieldInCell) * maxSource_; + } + } + } + + QPartFluid_.correctBoundaryConditions(); +} + +void heatTransferRanzMarshall::addEnergyContribution(volScalarField& Qsource) const +{ + Qsource += QPartFluid_; +} + +void heatTransferRanzMarshall::addEnergyCoefficient(volScalarField& Qsource) const +{ + if(implicit_) + { + Qsource += QPartFluidCoeff_; + } +} + +scalar heatTransferRanzMarshall::Nusselt(scalar voidfraction, scalar Rep, scalar Pr) const +{ + return (2 + 0.6 * Foam::pow(Rep,0.5) * Foam::pow(Pr,0.33)); +} + +void heatTransferRanzMarshall::heatFlux(label index, scalar h, scalar As, scalar Tfluid, scalar cg3) +{ + scalar hAs = h * As * cg3; + + if (particleCloud_.getParticleEffVolFactors()) + { + scalar effVolFac = particleCloud_.particleEffVolFactor(index); + hAs *= effVolFac; + } + + partHeatFlux_[index][0] = - hAs * partTemp_[index][0]; + if(!implicit_) + { + partHeatFlux_[index][0] += hAs * Tfluid; + } + else + { + partHeatFluxCoeff_[index][0] = hAs; + } +} + +void heatTransferRanzMarshall::giveData() +{ + // Info << "total convective particle-fluid heat flux [W] (Eulerian) = " << gSum(QPartFluid_*1.0*QPartFluid_.mesh().V()) << endl; + if (calcTotalHeatFlux_) + { + reduce(totalHeatFlux_, sumOp()); + Info << "total convective particle-fluid heat flux [W] = " << totalHeatFlux_ << endl; + } + particleCloud_.dataExchangeM().giveData(partHeatFluxName_,"scalar-atom", partHeatFlux_); +} + +void heatTransferRanzMarshall::postFlow() +{ + if(implicit_) + { + label cellI; + scalar Tfluid(0.0); + scalar Tpart(0.0); + interpolationCellPoint TInterpolator_(tempField_); + + totalHeatFlux_ = 0.0; + + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + cellI = particleCloud_.cellIDs()[index][0]; + if(cellI >= 0) + { + if(interpolation_) + { + vector position = particleCloud_.position(index); + Tfluid = TInterpolator_.interpolate(position,cellI); + } + else + { + Tfluid = tempField_[cellI]; + } + + Tpart = partTemp_[index][0]; + partHeatFlux_[index][0] = (Tfluid - Tpart) * partHeatFluxCoeff_[index][0]; + if (calcTotalHeatFlux_) + { + totalHeatFlux_ += partHeatFlux_[index][0]; + } + } + } + } + giveData(); +} + + +void heatTransferRanzMarshall::partTempField() +{ + partTempField_.primitiveFieldRef() = 0.0; + particleCloud_.averagingM().resetWeightFields(); + particleCloud_.averagingM().setScalarAverage + ( + partTempField_, + partTemp_, + particleCloud_.particleWeights(), + particleCloud_.averagingM().UsWeightField(), + NULL + ); + + dimensionedScalar denom = partTempAve_ - partRefTemp_; + if (denom.value() < SMALL && denom.value() > -SMALL) denom.value() = SMALL; + partRelTempField_ = (partTempField_ - partTempAve_) / denom; + + Info << "heatTransferRanzMarshall: average part. temp = " << partTempAve_.value() << endl; +} + +void heatTransferRanzMarshall::initPartTemp() +{ + label cellI = 0; + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + cellI = particleCloud_.cellIDs()[index][0]; + if(cellI >= 0) + { + partTemp_[index][0] = partTempField_[cellI]; + } + } +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // + diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferRanzMarshall/heatTransferRanzMarshall.H b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferRanzMarshall/heatTransferRanzMarshall.H new file mode 100644 index 00000000..da5b4c35 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/heatTransferRanzMarshall/heatTransferRanzMarshall.H @@ -0,0 +1,177 @@ +/*---------------------------------------------------------------------------*\ +License + + This 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 code 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 code. If not, see . + + Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria + + Description + Correlation for Nusselt number according to + Ranz and Marshall, Chem. Eng. Prog. 48.3 (1952) + +\*---------------------------------------------------------------------------*/ + +#ifndef heatTransferRanzMarshall_H +#define heatTransferRanzMarshall_H + +#include "fvCFD.H" +#include "cfdemCloudEnergy.H" +#include "energyModel.H" +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class heatTransferRanzMarshall Declaration +\*---------------------------------------------------------------------------*/ + +class heatTransferRanzMarshall +: + public energyModel +{ +protected: + + dictionary propsDict_; + + bool multiTypes_; + + bool expNusselt_; + + bool interpolation_; + + bool verbose_; + + bool implicit_; + + bool calcTotalHeatFlux_; + + bool initPartTemp_; + + scalar totalHeatFlux_; + + scalar NusseltScalingFactor_; + + word QPartFluidName_; + + volScalarField QPartFluid_; + + word QPartFluidCoeffName_; + + volScalarField QPartFluidCoeff_; + + mutable volScalarField partTempField_; + + volScalarField partRelTempField_; + + volScalarField ReField_; + + volScalarField NuField_; + + dimensionedScalar partRefTemp_; + + bool calcPartTempField_; + + dimensionedScalar partTempAve_; + + word tempFieldName_; + + const volScalarField& tempField_; // ref to temperature field + + word voidfractionFieldName_; + + const volScalarField& voidfraction_; // ref to voidfraction field + + scalar maxSource_; // max (limited) value of src field + + word velFieldName_; + + const volVectorField& U_; + + word densityFieldName_; + + const volScalarField& rho_; + + word partTempName_; + + mutable double **partTemp_; + + word partHeatFluxName_; + + mutable double **partHeatFlux_; + + mutable double **partHeatFluxCoeff_; + + mutable double **partRe_; + + mutable double **partNu_; + + mutable scalar scaleDia_; + + scalarList typeCG_; + + void allocateMyArrays() const; + + void partTempField(); + + scalar Nusselt(scalar, scalar, scalar) const; + + virtual void giveData(); + + virtual void heatFlux(label, scalar, scalar, scalar, scalar cg3 = 1.0); + + virtual void initPartTemp(); + +public: + + //- Runtime type information + TypeName("heatTransferRanzMarshall"); + + // Constructors + + //- Construct from components + heatTransferRanzMarshall + ( + const dictionary& dict, + cfdemCloudEnergy& sm + ); + + + // Destructor + + virtual ~heatTransferRanzMarshall(); + + + // Member Functions + + void addEnergyContribution(volScalarField&) const; + + void addEnergyCoefficient(volScalarField&) const; + + void calcEnergyContribution(); + + void postFlow(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // + diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/reactionHeat/reactionHeat.C b/src/lagrangian/cfdemParticle/subModels/energyModel/reactionHeat/reactionHeat.C index 3a243fc7..a5f3e2e1 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/reactionHeat/reactionHeat.C +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/reactionHeat/reactionHeat.C @@ -46,6 +46,7 @@ reactionHeat::reactionHeat energyModel(dict,sm), propsDict_(dict.subDict(typeName + "Props")), interpolation_(propsDict_.lookupOrDefault("interpolation",false)), + verbose_(propsDict_.lookupOrDefault("verbose",false)), mesh_(sm.mesh()), maxSource_(1e30), reactionHeatName_(propsDict_.lookupOrDefault("reactionHeatName","reactionHeat")), @@ -98,6 +99,14 @@ void reactionHeat::calcEnergyContribution() particleCloud_.dataExchangeM().getData(reactionHeatName_,"scalar-atom",reactionHeat_); + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + if (verbose_ && index>=0 && index < 2) + { + Pout << "reactionHeat = " << reactionHeat_[index][0] << endl; + } + } + reactionHeatField_.primitiveFieldRef() = 0.0; reactionHeatField_.boundaryFieldRef() = 0.0; diff --git a/src/lagrangian/cfdemParticle/subModels/energyModel/reactionHeat/reactionHeat.H b/src/lagrangian/cfdemParticle/subModels/energyModel/reactionHeat/reactionHeat.H index bcd5501e..4ebd7a02 100644 --- a/src/lagrangian/cfdemParticle/subModels/energyModel/reactionHeat/reactionHeat.H +++ b/src/lagrangian/cfdemParticle/subModels/energyModel/reactionHeat/reactionHeat.H @@ -48,6 +48,8 @@ protected: bool interpolation_; + bool verbose_; + const fvMesh& mesh_; scalar maxSource_; diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C index 59c39254..18381aa3 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.C @@ -148,6 +148,7 @@ void BeetstraDrag::setForce() const else if (particleCloud_.cg() > 1) { scaleDia_=particleCloud_.cg(); + typeCG_[0] = scaleDia_; Info << "Beetstra using scale from liggghts cg = " << scaleDia_ << endl; } diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.H b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.H index c2128855..cfeeea39 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.H +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/BeetstraDrag/BeetstraDrag.H @@ -17,6 +17,11 @@ Description drag law for monodisperse systems according to Beetstra et al. AIChE J 53.2 (2007) +Reference + R. Beetstra, M.A. van der Hoef, J.A.M. Kuipers + "Drag force of intermediate Reynolds number flow past mono- and bidisperse arrays of spheres" + AIChE Journal, 53 (2007) + SourceFiles BeetstraDrag.C \*---------------------------------------------------------------------------*/ @@ -61,7 +66,7 @@ protected: mutable scalar scaleDia_; - scalarList typeCG_; + mutable scalarList typeCG_; mutable scalar scaleDrag_; @@ -86,12 +91,12 @@ protected: virtual void adaptVoidfraction(double&, label) const {} virtual scalar effDiameter(double d, label cellI, label index) const {return d;} - + virtual scalar meanSauterDiameter(double d, label cellI) const {return d;} double F(double, double) const; - double terminalVelocity(double, double, double, double, double, double) const; + double terminalVelocity(double, double, double, double, double, double) const; double a(double) const; diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/GidaspowDrag/GidaspowDrag.H b/src/lagrangian/cfdemParticle/subModels/forceModel/GidaspowDrag/GidaspowDrag.H index 76102bcb..db1e9be4 100644 --- a/src/lagrangian/cfdemParticle/subModels/forceModel/GidaspowDrag/GidaspowDrag.H +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/GidaspowDrag/GidaspowDrag.H @@ -34,6 +34,11 @@ Description - splits off explicit drag component due to fluctuation in fluid and particle velocity (optional via forceSubModel "ImExCorr") +Reference + D. Gidaspow + "Multiphase flow and fluidization: Continuum and kinetic theory description", + 1994 + Class GidaspowDrag diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/deactivateForce/deactivateForce.C b/src/lagrangian/cfdemParticle/subModels/forceModel/deactivateForce/deactivateForce.C new file mode 100644 index 00000000..0f0d792c --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/deactivateForce/deactivateForce.C @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . +\*---------------------------------------------------------------------------*/ + +#include "error.H" + +#include "deactivateForce.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(deactivateForce, 0); + +addToRunTimeSelectionTable +( + forceModel, + deactivateForce, + dictionary +); + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +deactivateForce::deactivateForce +( + const dictionary& dict, + cfdemCloud& sm +) +: + forceModel(dict,sm) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +deactivateForce::~deactivateForce() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void deactivateForce::setForce() const +{} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/deactivateForce/deactivateForce.H b/src/lagrangian/cfdemParticle/subModels/forceModel/deactivateForce/deactivateForce.H new file mode 100644 index 00000000..4a3682ac --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/deactivateForce/deactivateForce.H @@ -0,0 +1,78 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . +\*---------------------------------------------------------------------------*/ + +#ifndef deactivateForce_H +#define deactivateForce_H + +#include "forceModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class deactivateForce Declaration +\*---------------------------------------------------------------------------*/ + +class deactivateForce +: + public forceModel +{ +private: + +public: + + //- Runtime type information + TypeName("deactivateForce"); + + + // Constructors + + //- Construct from components + deactivateForce + ( + const dictionary& dict, + cfdemCloud& sm + ); + + // Destructor + + ~deactivateForce(); + + + // Member Functions + void setForce() const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/directedDiffusiveRelaxation/directedDiffusiveRelaxation.C b/src/lagrangian/cfdemParticle/subModels/forceModel/directedDiffusiveRelaxation/directedDiffusiveRelaxation.C new file mode 100644 index 00000000..8f10efe4 --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/directedDiffusiveRelaxation/directedDiffusiveRelaxation.C @@ -0,0 +1,239 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . +\*---------------------------------------------------------------------------*/ + +#include "error.H" + +#include "directedDiffusiveRelaxation.H" +#include "addToRunTimeSelectionTable.H" +#include "OFstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(directedDiffusiveRelaxation, 0); + +addToRunTimeSelectionTable +( + forceModel, + directedDiffusiveRelaxation, + dictionary +); + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +directedDiffusiveRelaxation::directedDiffusiveRelaxation +( + const dictionary& dict, + cfdemCloud& sm +) +: + forceModel(dict,sm), + propsDict_(dict.subDict(typeName + "Props")), + implicit_(propsDict_.lookupOrDefault("implicit", true)), + interpolate_(propsDict_.lookupOrDefault("interpolation", false)), + measureDiff_(propsDict_.lookupOrDefault("measureDiff", false)), + recErrorFile_("recurrenceError"), + ignoreCellsName_(propsDict_.lookupOrDefault("ignoreCellsName","none")), + ignoreCells_(), + existIgnoreCells_(true), + voidfractionFieldName_(propsDict_.lookupOrDefault("voidfractionFieldName","voidfraction")), + voidfraction_(sm.mesh().lookupObject (voidfractionFieldName_)), + voidfractionRecFieldName_(propsDict_.lookupOrDefault("voidfractionRecFieldName","voidfractionRec")), + voidfractionRec_(sm.mesh().lookupObject (voidfractionRecFieldName_)), + critVoidfraction_(propsDict_.lookupOrDefault("critVoidfraction", 1.0)), + D0_(readScalar(propsDict_.lookup("D0"))), + maxDisplacement_(propsDict_.lookupOrDefault("maxDisplacement", -1.0)), + correctedField_ + ( IOobject + ( + "correctedField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + voidfraction_ + ), + relaxStream_ + ( IOobject + ( + "relaxStream", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedVector("zero",dimensionSet(0,1,-1,0,0), vector::zero) + ), + DField_ + ( IOobject + ( + "DField", + sm.mesh().time().timeName(), + sm.mesh(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + sm.mesh(), + dimensionedScalar("zero", dimensionSet(0,2,-1,0,0,0,0), 0.0), + "zeroGradient" + ), + dtCFD_(voidfraction_.mesh().time().deltaTValue()), + dtDEM_(particleCloud_.dataExchangeM().DEMts()), + timeFac_(1.0), + relaxForT_(propsDict_.lookupOrDefault("relaxForT", -1.0)) +{ + if(ignoreCellsName_ != "none") + { + ignoreCells_.set(new cellSet(particleCloud_.mesh(),ignoreCellsName_)); + Info << "directedDiffusiveRelaxation: ignoring fluctuations in cellSet " << ignoreCells_().name() << + " with " << ignoreCells_().size() << " cells." << endl; + } + else existIgnoreCells_ = false; + if (dtDEM_ > dtCFD_) timeFac_ = dtCFD_ / dtDEM_; +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +directedDiffusiveRelaxation::~directedDiffusiveRelaxation() +{ +} + +// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * // + +bool directedDiffusiveRelaxation::ignoreCell(label cell) const +{ + if (!existIgnoreCells_) return false; + else return ignoreCells_()[cell]; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void directedDiffusiveRelaxation::setForce() const +{ + if (relaxForT_ >= 0.0 && particleCloud_.mesh().foundObject("lastJumpTime")) + { + const IOdictionary& lastJumpTimeDict(particleCloud_.mesh().lookupObject("lastJumpTime")); + scalar lastJumpTime = lastJumpTimeDict.lookupOrDefault("lastJumpTime",-1e5); + scalar currTime = particleCloud_.mesh().time().timeOutputValue(); + if (currTime - lastJumpTime > relaxForT_) return; + } + + relax(D0_); + + relaxStream_ = DField_ * fvc::grad(correctedField_ - voidfractionRec_); + + vector position(0,0,0); + scalar voidfraction(0.0); + vector flucU(0,0,0); + label cellI=0; + + interpolationCellPoint voidfractionInterpolator_(voidfraction_); + interpolationCellPoint relaxStreamInterpolator_(relaxStream_); + + scalar maxVel = maxDisplacement_ / dtDEM_; + + for(int index = 0;index < particleCloud_.numberOfParticles(); ++index) + { + cellI = particleCloud_.cellIDs()[index][0]; + if (cellI > -1 && !ignoreCell(cellI)) + { + { + if (interpolate_) + { + position = particleCloud_.position(index); + voidfraction = voidfractionInterpolator_.interpolate(position,cellI); + flucU = relaxStreamInterpolator_.interpolate(position,cellI); + } + else + { + voidfraction = voidfraction_[cellI]; + flucU = relaxStream_[cellI]; + } + + if (voidfraction > 1.0-SMALL) voidfraction = 1.0 - SMALL; + flucU /= (1-voidfraction); + flucU *= timeFac_; + + scalar magFlucU = mag(flucU); + if (maxVel > 0.0 && magFlucU > maxVel) + { + flucU *= maxVel / magFlucU; + } + + // write particle based data to global array + for(int j=0;j<3;j++) + { + particleCloud_.particleFlucVels()[index][j] += flucU[j]; + } + } + } + } + + if (measureDiff_) + { + dimensionedScalar diff( fvc::domainIntegrate( sqr( voidfraction_ - voidfractionRec_ ) ) ); + scalar t = particleCloud_.mesh().time().timeOutputValue(); + recErrorFile_ << t << "\t" << diff.value() << endl; + } +} + +void directedDiffusiveRelaxation::relax(scalar D0) const +{ + correctedField_.oldTime() = voidfraction_; + forAll(DField_, cellI) + { + if(voidfraction_[cellI] > 0.99) DField_[cellI] = 0.0; + else DField_[cellI] = D0; + } + + if (implicit_) + { + solve + ( + fvm::ddt(correctedField_) + -fvm::laplacian(DField_, correctedField_) + == + -fvc::laplacian(DField_, voidfractionRec_) + ); + } + else + { + correctedField_ = voidfraction_; + } +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/directedDiffusiveRelaxation/directedDiffusiveRelaxation.H b/src/lagrangian/cfdemParticle/subModels/forceModel/directedDiffusiveRelaxation/directedDiffusiveRelaxation.H new file mode 100644 index 00000000..04487e5e --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/directedDiffusiveRelaxation/directedDiffusiveRelaxation.H @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . +\*---------------------------------------------------------------------------*/ + +#ifndef directedDiffusiveRelaxation_H +#define directedDiffusiveRelaxation_H + +#include "forceModel.H" +#include "interpolationCellPoint.H" +#include "autoPtr.H" +#include "cellSet.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class directedDiffusiveRelaxation Declaration +\*---------------------------------------------------------------------------*/ + +class directedDiffusiveRelaxation +: + public forceModel +{ +private: + dictionary propsDict_; + + bool implicit_; + + bool interpolate_; + + bool measureDiff_; + + mutable OFstream recErrorFile_; + + // ignore fluctuations in region + word ignoreCellsName_; + + autoPtr ignoreCells_; + + bool existIgnoreCells_; + + word voidfractionFieldName_; + + const volScalarField& voidfraction_; + + word voidfractionRecFieldName_; + + const volScalarField& voidfractionRec_; + + scalar critVoidfraction_; + + scalar D0_; + + scalar maxDisplacement_; + + mutable volScalarField correctedField_; + + mutable volVectorField relaxStream_; + + mutable volScalarField DField_; + + const scalar dtCFD_; + + const scalar dtDEM_; + + scalar timeFac_; + + scalar relaxForT_; + + void relax(scalar) const; + + bool ignoreCell(label) const; + + +public: + + //- Runtime type information + TypeName("directedDiffusiveRelaxation"); + + + // Constructors + + //- Construct from components + directedDiffusiveRelaxation + ( + const dictionary& dict, + cfdemCloud& sm + ); + + // Destructor + + ~directedDiffusiveRelaxation(); + + + // Member Functions + void setForce() const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/lagrangian/cfdemParticle/subModels/forceModel/evaluateFluctuations/evaluateFluctuations.C b/src/lagrangian/cfdemParticle/subModels/forceModel/evaluateFluctuations/evaluateFluctuations.C new file mode 100644 index 00000000..573e708d --- /dev/null +++ b/src/lagrangian/cfdemParticle/subModels/forceModel/evaluateFluctuations/evaluateFluctuations.C @@ -0,0 +1,186 @@ +/*---------------------------------------------------------------------------*\ + CFDEMcoupling academic - Open Source CFD-DEM coupling + + Contributing authors: + Thomas Lichtenegger + Copyright (C) 2015- Johannes Kepler University, Linz +------------------------------------------------------------------------------- +License + This file is part of CFDEMcoupling academic. + + CFDEMcoupling academic 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. + + CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see . +\*---------------------------------------------------------------------------*/ + +#include "error.H" + +#include "evaluateFluctuations.H" +#include "addToRunTimeSelectionTable.H" +#include "OFstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(evaluateFluctuations, 0); + +addToRunTimeSelectionTable +( + forceModel, + evaluateFluctuations, + dictionary +); + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from components +evaluateFluctuations::evaluateFluctuations +( + const dictionary& dict, + cfdemCloud& sm +) +: + forceModel(dict,sm), + propsDict_(dict.subDict(typeName + "Props")), + interpolate_(propsDict_.lookupOrDefault("interpolation", false)), + activeCellsName_(propsDict_.lookupOrDefault
+ +
asdf asdf asdf asdf 22
+ {% trans %}Please activate JavaScript to enable the search + functionality.{% endtrans %} +
{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}
{{ context|e }}