├── .github ├── CONTRIBUTING.md └── FUNDING.yml ├── .gitignore ├── .zenodo.json ├── CITATION.bib ├── LICENSE ├── LICENSE-CC-0 ├── LICENSE-CC-BY ├── LICENSE-CC-BY-ND ├── Makefile ├── README.md ├── babel-plugin-macros.config.js ├── package.json ├── public ├── favicon.ico ├── images │ ├── OF │ │ ├── OF.png │ │ ├── combustion │ │ │ └── combustion.png │ │ ├── compressible │ │ │ └── compressible.png │ │ ├── heatTransfer │ │ │ └── heatTransfer.png │ │ ├── incompressible │ │ │ ├── incompressible.png │ │ │ └── simpleFoam │ │ │ │ ├── airFoil2D │ │ │ │ └── airFoil2D.png │ │ │ │ ├── backwardFacingStep2D │ │ │ │ └── backwardFacingStep2D.png │ │ │ │ ├── bump2D │ │ │ │ └── bump2D.png │ │ │ │ ├── mixerVessel2D │ │ │ │ └── mixerVessel2D.png │ │ │ │ ├── motorBike │ │ │ │ └── motorBike.png │ │ │ │ ├── pitzDaily │ │ │ │ └── pitzDaily.png │ │ │ │ ├── simpleFoam.png │ │ │ │ ├── turbineSiting │ │ │ │ └── turbineSiting.png │ │ │ │ └── windAroundBuildings │ │ │ │ └── windAroundBuildings.png │ │ ├── lagrangian │ │ │ └── lagrangian.png │ │ └── multiphase │ │ │ └── multiphase.png │ ├── Tools │ │ ├── ITHACA-FV │ │ │ └── ITHACA-FV.png │ │ ├── Tools.png │ │ └── VTK │ │ │ └── VTK.png │ ├── card.png │ └── constructionSolver.png ├── index.html └── manifest.json └── src ├── App.js ├── components ├── Main │ ├── About.jsx │ ├── Error.jsx │ ├── Fader.jsx │ ├── Footer.jsx │ ├── Navigation.jsx │ ├── ShowCards.jsx │ ├── index.jsx │ ├── list.js │ ├── logoDark.svg │ ├── logoLight.svg │ ├── placeholder.png │ ├── useDarkMode.js │ └── worker.js ├── OF │ ├── GenericView.jsx │ ├── Incompressible │ │ ├── SimpleFoam │ │ │ ├── Bump2D.jsx │ │ │ ├── MixerVessel2D.jsx │ │ │ ├── MotorBike.jsx │ │ │ ├── PitzDaily.jsx │ │ │ ├── TurbineSiting.jsx │ │ │ ├── WindAroundBuildings.jsx │ │ │ ├── index.jsx │ │ │ └── list.js │ │ ├── index.jsx │ │ └── list.js │ ├── ROMView.jsx │ ├── index.jsx │ └── list.js ├── Tools │ ├── ITHACA-FV │ │ └── Steady.jsx │ ├── VTK │ │ └── Slicer.jsx │ ├── index.jsx │ └── list.js ├── index.js └── theme.js └── index.js /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How can I contribute? 2 | 3 | This document is a work in progress. More details will be shared soon. 4 | 5 | Your help is very welcome whether it is reporting or fixing a bug, suggesting enhancements or contributing with new code. 6 | 7 | You can reach us at the [cfd-xyz Slack channel](https://join.slack.com/t/cfd-xyz/shared_invite/zt-15qjacmzo-1woWqeklQ0IeXZb_F6ueaQ). 8 | 9 | ## Reporting Bugs 10 | 11 | Check existing issues and create a new one. 12 | 13 | ## Suggesting Enhancements 14 | 15 | Please suggest completely new features and minor improvements to existing functionalities. 16 | 17 | ## Code Contribution 18 | 19 | ### Local development 20 | 21 | You can easily install the web app locally and test new code. 22 | 23 | ### Pull requests 24 | 25 | Please create a personal fork of the project and open a pull request. 26 | 27 | ## License 28 | 29 | By contributing to this repository you agree that your contributions will be licensed under the MIT License. 30 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: "https://www.paypal.com/donate/?hosted_button_id=KKB4LH96E59A4" 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swp 3 | *.swo 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | /coverage 8 | /build 9 | .DS_Store 10 | .env.* 11 | .environment 12 | package-lock.json 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | par 17 | *.txt 18 | *.vtu 19 | *.vtp 20 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "

An open-source web app for generating and visualizing parametric CFD results

", 3 | "title": "simzero-oss/cfd-xyz", 4 | "upload_type": "software", 5 | "creators": [ 6 | { 7 | "orcid": "0000-0003-3271-6399", 8 | "name": "Carlos Pe\u00f1a-Monferrer" 9 | }, 10 | { 11 | "orcid": "0000-0002-8924-9544", 12 | "name": "Carmen D\u00edaz-Mar\u00edn" 13 | } 14 | ], 15 | "access_right": "open" 16 | } 17 | -------------------------------------------------------------------------------- /CITATION.bib: -------------------------------------------------------------------------------- 1 | @article{Pena-Monferrer_Diaz-Marin_2022, 2 | author={Peña-Monferrer, Carlos and Diaz-Marin, Carmen}, 3 | title={rom.js/cfd.xyz: An open-source framework for generating and visualizing parametric {CFD} results}, 4 | journal={OpenFOAM® Journal}, 5 | volume={2}, 6 | month={Oct.}, 7 | pages={143–148} 8 | DOI={10.51560/ofj.v2.83}, 9 | url={https://journal.openfoam.com/index.php/ofj/article/view/83}, 10 | year={2022}, 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Carlos Peña-Monferrer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE-CC-0: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /LICENSE-CC-BY: -------------------------------------------------------------------------------- 1 | Attribution 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution 4.0 International Public License 58 | 59 | By exercising the Licensed Rights (defined below), You accept and agree 60 | to be bound by the terms and conditions of this Creative Commons 61 | Attribution 4.0 International Public License ("Public License"). To the 62 | extent this Public License may be interpreted as a contract, You are 63 | granted the Licensed Rights in consideration of Your acceptance of 64 | these terms and conditions, and the Licensor grants You such rights in 65 | consideration of benefits the Licensor receives from making the 66 | Licensed Material available under these terms and conditions. 67 | 68 | 69 | Section 1 -- Definitions. 70 | 71 | a. Adapted Material means material subject to Copyright and Similar 72 | Rights that is derived from or based upon the Licensed Material 73 | and in which the Licensed Material is translated, altered, 74 | arranged, transformed, or otherwise modified in a manner requiring 75 | permission under the Copyright and Similar Rights held by the 76 | Licensor. For purposes of this Public License, where the Licensed 77 | Material is a musical work, performance, or sound recording, 78 | Adapted Material is always produced where the Licensed Material is 79 | synched in timed relation with a moving image. 80 | 81 | b. Adapter's License means the license You apply to Your Copyright 82 | and Similar Rights in Your contributions to Adapted Material in 83 | accordance with the terms and conditions of this Public License. 84 | 85 | c. Copyright and Similar Rights means copyright and/or similar rights 86 | closely related to copyright including, without limitation, 87 | performance, broadcast, sound recording, and Sui Generis Database 88 | Rights, without regard to how the rights are labeled or 89 | categorized. For purposes of this Public License, the rights 90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 91 | Rights. 92 | 93 | d. Effective Technological Measures means those measures that, in the 94 | absence of proper authority, may not be circumvented under laws 95 | fulfilling obligations under Article 11 of the WIPO Copyright 96 | Treaty adopted on December 20, 1996, and/or similar international 97 | agreements. 98 | 99 | e. Exceptions and Limitations means fair use, fair dealing, and/or 100 | any other exception or limitation to Copyright and Similar Rights 101 | that applies to Your use of the Licensed Material. 102 | 103 | f. Licensed Material means the artistic or literary work, database, 104 | or other material to which the Licensor applied this Public 105 | License. 106 | 107 | g. Licensed Rights means the rights granted to You subject to the 108 | terms and conditions of this Public License, which are limited to 109 | all Copyright and Similar Rights that apply to Your use of the 110 | Licensed Material and that the Licensor has authority to license. 111 | 112 | h. Licensor means the individual(s) or entity(ies) granting rights 113 | under this Public License. 114 | 115 | i. Share means to provide material to the public by any means or 116 | process that requires permission under the Licensed Rights, such 117 | as reproduction, public display, public performance, distribution, 118 | dissemination, communication, or importation, and to make material 119 | available to the public including in ways that members of the 120 | public may access the material from a place and at a time 121 | individually chosen by them. 122 | 123 | j. Sui Generis Database Rights means rights other than copyright 124 | resulting from Directive 96/9/EC of the European Parliament and of 125 | the Council of 11 March 1996 on the legal protection of databases, 126 | as amended and/or succeeded, as well as other essentially 127 | equivalent rights anywhere in the world. 128 | 129 | k. You means the individual or entity exercising the Licensed Rights 130 | under this Public License. Your has a corresponding meaning. 131 | 132 | 133 | Section 2 -- Scope. 134 | 135 | a. License grant. 136 | 137 | 1. Subject to the terms and conditions of this Public License, 138 | the Licensor hereby grants You a worldwide, royalty-free, 139 | non-sublicensable, non-exclusive, irrevocable license to 140 | exercise the Licensed Rights in the Licensed Material to: 141 | 142 | a. reproduce and Share the Licensed Material, in whole or 143 | in part; and 144 | 145 | b. produce, reproduce, and Share Adapted Material. 146 | 147 | 2. Exceptions and Limitations. For the avoidance of doubt, where 148 | Exceptions and Limitations apply to Your use, this Public 149 | License does not apply, and You do not need to comply with 150 | its terms and conditions. 151 | 152 | 3. Term. The term of this Public License is specified in Section 153 | 6(a). 154 | 155 | 4. Media and formats; technical modifications allowed. The 156 | Licensor authorizes You to exercise the Licensed Rights in 157 | all media and formats whether now known or hereafter created, 158 | and to make technical modifications necessary to do so. The 159 | Licensor waives and/or agrees not to assert any right or 160 | authority to forbid You from making technical modifications 161 | necessary to exercise the Licensed Rights, including 162 | technical modifications necessary to circumvent Effective 163 | Technological Measures. For purposes of this Public License, 164 | simply making modifications authorized by this Section 2(a) 165 | (4) never produces Adapted Material. 166 | 167 | 5. Downstream recipients. 168 | 169 | a. Offer from the Licensor -- Licensed Material. Every 170 | recipient of the Licensed Material automatically 171 | receives an offer from the Licensor to exercise the 172 | Licensed Rights under the terms and conditions of this 173 | Public License. 174 | 175 | b. No downstream restrictions. You may not offer or impose 176 | any additional or different terms or conditions on, or 177 | apply any Effective Technological Measures to, the 178 | Licensed Material if doing so restricts exercise of the 179 | Licensed Rights by any recipient of the Licensed 180 | Material. 181 | 182 | 6. No endorsement. Nothing in this Public License constitutes or 183 | may be construed as permission to assert or imply that You 184 | are, or that Your use of the Licensed Material is, connected 185 | with, or sponsored, endorsed, or granted official status by, 186 | the Licensor or others designated to receive attribution as 187 | provided in Section 3(a)(1)(A)(i). 188 | 189 | b. Other rights. 190 | 191 | 1. Moral rights, such as the right of integrity, are not 192 | licensed under this Public License, nor are publicity, 193 | privacy, and/or other similar personality rights; however, to 194 | the extent possible, the Licensor waives and/or agrees not to 195 | assert any such rights held by the Licensor to the limited 196 | extent necessary to allow You to exercise the Licensed 197 | Rights, but not otherwise. 198 | 199 | 2. Patent and trademark rights are not licensed under this 200 | Public License. 201 | 202 | 3. To the extent possible, the Licensor waives any right to 203 | collect royalties from You for the exercise of the Licensed 204 | Rights, whether directly or through a collecting society 205 | under any voluntary or waivable statutory or compulsory 206 | licensing scheme. In all other cases the Licensor expressly 207 | reserves any right to collect such royalties. 208 | 209 | 210 | Section 3 -- License Conditions. 211 | 212 | Your exercise of the Licensed Rights is expressly made subject to the 213 | following conditions. 214 | 215 | a. Attribution. 216 | 217 | 1. If You Share the Licensed Material (including in modified 218 | form), You must: 219 | 220 | a. retain the following if it is supplied by the Licensor 221 | with the Licensed Material: 222 | 223 | i. identification of the creator(s) of the Licensed 224 | Material and any others designated to receive 225 | attribution, in any reasonable manner requested by 226 | the Licensor (including by pseudonym if 227 | designated); 228 | 229 | ii. a copyright notice; 230 | 231 | iii. a notice that refers to this Public License; 232 | 233 | iv. a notice that refers to the disclaimer of 234 | warranties; 235 | 236 | v. a URI or hyperlink to the Licensed Material to the 237 | extent reasonably practicable; 238 | 239 | b. indicate if You modified the Licensed Material and 240 | retain an indication of any previous modifications; and 241 | 242 | c. indicate the Licensed Material is licensed under this 243 | Public License, and include the text of, or the URI or 244 | hyperlink to, this Public License. 245 | 246 | 2. You may satisfy the conditions in Section 3(a)(1) in any 247 | reasonable manner based on the medium, means, and context in 248 | which You Share the Licensed Material. For example, it may be 249 | reasonable to satisfy the conditions by providing a URI or 250 | hyperlink to a resource that includes the required 251 | information. 252 | 253 | 3. If requested by the Licensor, You must remove any of the 254 | information required by Section 3(a)(1)(A) to the extent 255 | reasonably practicable. 256 | 257 | 4. If You Share Adapted Material You produce, the Adapter's 258 | License You apply must not prevent recipients of the Adapted 259 | Material from complying with this Public License. 260 | 261 | 262 | Section 4 -- Sui Generis Database Rights. 263 | 264 | Where the Licensed Rights include Sui Generis Database Rights that 265 | apply to Your use of the Licensed Material: 266 | 267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 268 | to extract, reuse, reproduce, and Share all or a substantial 269 | portion of the contents of the database; 270 | 271 | b. if You include all or a substantial portion of the database 272 | contents in a database in which You have Sui Generis Database 273 | Rights, then the database in which You have Sui Generis Database 274 | Rights (but not its individual contents) is Adapted Material; and 275 | 276 | c. You must comply with the conditions in Section 3(a) if You Share 277 | all or a substantial portion of the contents of the database. 278 | 279 | For the avoidance of doubt, this Section 4 supplements and does not 280 | replace Your obligations under this Public License where the Licensed 281 | Rights include other Copyright and Similar Rights. 282 | 283 | 284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 285 | 286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 296 | 297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 306 | 307 | c. The disclaimer of warranties and limitation of liability provided 308 | above shall be interpreted in a manner that, to the extent 309 | possible, most closely approximates an absolute disclaimer and 310 | waiver of all liability. 311 | 312 | 313 | Section 6 -- Term and Termination. 314 | 315 | a. This Public License applies for the term of the Copyright and 316 | Similar Rights licensed here. However, if You fail to comply with 317 | this Public License, then Your rights under this Public License 318 | terminate automatically. 319 | 320 | b. Where Your right to use the Licensed Material has terminated under 321 | Section 6(a), it reinstates: 322 | 323 | 1. automatically as of the date the violation is cured, provided 324 | it is cured within 30 days of Your discovery of the 325 | violation; or 326 | 327 | 2. upon express reinstatement by the Licensor. 328 | 329 | For the avoidance of doubt, this Section 6(b) does not affect any 330 | right the Licensor may have to seek remedies for Your violations 331 | of this Public License. 332 | 333 | c. For the avoidance of doubt, the Licensor may also offer the 334 | Licensed Material under separate terms or conditions or stop 335 | distributing the Licensed Material at any time; however, doing so 336 | will not terminate this Public License. 337 | 338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 339 | License. 340 | 341 | 342 | Section 7 -- Other Terms and Conditions. 343 | 344 | a. The Licensor shall not be bound by any additional or different 345 | terms or conditions communicated by You unless expressly agreed. 346 | 347 | b. Any arrangements, understandings, or agreements regarding the 348 | Licensed Material not stated herein are separate from and 349 | independent of the terms and conditions of this Public License. 350 | 351 | 352 | Section 8 -- Interpretation. 353 | 354 | a. For the avoidance of doubt, this Public License does not, and 355 | shall not be interpreted to, reduce, limit, restrict, or impose 356 | conditions on any use of the Licensed Material that could lawfully 357 | be made without permission under this Public License. 358 | 359 | b. To the extent possible, if any provision of this Public License is 360 | deemed unenforceable, it shall be automatically reformed to the 361 | minimum extent necessary to make it enforceable. If the provision 362 | cannot be reformed, it shall be severed from this Public License 363 | without affecting the enforceability of the remaining terms and 364 | conditions. 365 | 366 | c. No term or condition of this Public License will be waived and no 367 | failure to comply consented to unless expressly agreed to by the 368 | Licensor. 369 | 370 | d. Nothing in this Public License constitutes or may be interpreted 371 | as a limitation upon, or waiver of, any privileges and immunities 372 | that apply to the Licensor or You, including from the legal 373 | processes of any jurisdiction or authority. 374 | 375 | 376 | ======================================================================= 377 | 378 | Creative Commons is not a party to its public 379 | licenses. Notwithstanding, Creative Commons may elect to apply one of 380 | its public licenses to material it publishes and in those instances 381 | will be considered the “Licensor.” The text of the Creative Commons 382 | public licenses is dedicated to the public domain under the CC0 Public 383 | Domain Dedication. Except for the limited purpose of indicating that 384 | material is shared under a Creative Commons public license or as 385 | otherwise permitted by the Creative Commons policies published at 386 | creativecommons.org/policies, Creative Commons does not authorize the 387 | use of the trademark "Creative Commons" or any other trademark or logo 388 | of Creative Commons without its prior written consent including, 389 | without limitation, in connection with any unauthorized modifications 390 | to any of its public licenses or any other arrangements, 391 | understandings, or agreements concerning use of licensed material. For 392 | the avoidance of doubt, this paragraph does not form part of the 393 | public licenses. 394 | 395 | Creative Commons may be contacted at creativecommons.org. 396 | -------------------------------------------------------------------------------- /LICENSE-CC-BY-ND: -------------------------------------------------------------------------------- 1 | Attribution-NoDerivatives 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. 6 | 7 | Using Creative Commons Public Licenses 8 | 9 | Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. 10 | 11 | Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors 12 | 13 | Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor's permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public : wiki.creativecommons.org/Considerations_for_licensees 14 | 15 | Creative Commons Attribution-NoDerivatives 4.0 International Public License 16 | 17 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NoDerivatives 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. 18 | 19 | Section 1 – Definitions. 20 | 21 | a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 22 | b. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 23 | c. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 24 | d. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 25 | e. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 26 | f. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 27 | g. Licensor means the individual(s) or entity(ies) granting rights under this Public License. 28 | h. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 29 | i. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 30 | j. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. 31 | Section 2 – Scope. 32 | 33 | a. License grant. 34 | Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 35 | A. reproduce and Share the Licensed Material, in whole or in part; and 36 | B. produce and reproduce, but not Share, Adapted Material. 37 | Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 38 | Term. The term of this Public License is specified in Section 6(a). 39 | Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 40 | Downstream recipients. 41 | A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 42 | B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 43 | No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 44 | b. Other rights. 45 | Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 46 | Patent and trademark rights are not licensed under this Public License. 47 | To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. 48 | Section 3 – License Conditions. 49 | 50 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 51 | 52 | a. Attribution. 53 | If You Share the Licensed Material, You must: 54 | A. retain the following if it is supplied by the Licensor with the Licensed Material: 55 | i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 56 | ii. a copyright notice; 57 | iii. a notice that refers to this Public License; 58 | iv. a notice that refers to the disclaimer of warranties; 59 | v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 60 | B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 61 | C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 62 | For the avoidance of doubt, You do not have permission under this Public License to Share Adapted Material. 63 | You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 64 | If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 65 | Section 4 – Sui Generis Database Rights. 66 | 67 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 68 | 69 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database, provided You do not Share Adapted Material; 70 | b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and 71 | c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 72 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. 73 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 74 | 75 | a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. 76 | b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. 77 | c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 78 | Section 6 – Term and Termination. 79 | 80 | a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 81 | b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 82 | automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 83 | upon express reinstatement by the Licensor. 84 | c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 85 | d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 86 | e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 87 | Section 7 – Other Terms and Conditions. 88 | 89 | a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 90 | b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. 91 | Section 8 – Interpretation. 92 | 93 | a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 94 | b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 95 | c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 96 | d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. 97 | Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." The text of the Creative Commons public licenses is dedicated to the public domain under the CC0 Public Domain Dedication. Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. 98 | 99 | Creative Commons may be contacted at creativecommons.org. 100 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | # This work is licensed under the terms of the MIT license. 3 | # For a copy, see . 4 | 5 | SHELL := /bin/bash 6 | 7 | cfd-xyz-version := v1.1.0 8 | surrogates-version := v1.1.0 9 | cfd-xyz-image := ghcr.io/simzero-oss/cfd-xyz:$(cfd-xyz-version) 10 | cfd-xyz := docker run --publish 5000:3000 --user node -it --entrypoint "" -w /work -v ${PWD}:/work $(cfd-xyz-image) 11 | surrogates-data := surrogates_$(surrogates-version) 12 | simulations-data := simulations_${surrogates-version} 13 | surrogates-url := https://github.com/simzero-oss/cfd-xyz-data/raw/main/$(surrogates-data).zip 14 | simulations-url := https://github.com/simzero-oss/cfd-xyz-data/raw/main/$(simulations-data).zip 15 | 16 | all: install data build start 17 | all-docker: install-docker data-docker build-docker start-docker 18 | 19 | install: 20 | npm install 21 | build: 22 | npm run build 23 | start: 24 | npm start 25 | data: 26 | curl -L $(surrogates-url) -o surrogates.zip 27 | curl -L $(simulations-url) -o simulations.zip 28 | unzip surrogates.zip -d public/ 29 | unzip simulations.zip -d public/ 30 | 31 | install-docker: 32 | $(cfd-xyz) npm install 33 | build-docker: 34 | $(cfd-xyz) npm run build 35 | start-docker: 36 | echo "Serving on http://localhost:5000" 37 | $(cfd-xyz) npm start 38 | data-docker: 39 | $(cfd-xyz) curl -LJ0 $(surrogates-url) -o surrogates.zip 40 | $(cfd-xyz) curl -LJ0 $(simulations-url) -o simulations.zip 41 | unzip surrogates.zip -d public/ 42 | unzip simulations.zip -d public/ 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Important Notice:** This repository will be subject to important changes soon. Please be aware that some features or functionality may no longer be available, and new features or functionality may be added that could affect your usage of the repository. 2 | 3 | 4 | # cfd.xyz - An open-source web app for generating and visualizing parametric CFD results 5 | 6 | [![Website shields.io](https://img.shields.io/website-up-down-green-red/http/shields.io.svg)](http://cfd.xyz) 7 | [![Docker](https://badgen.net/badge/icon/docker?icon=docker&label)](https://github.com/orgs/simzero-oss/packages/container/package/cfd-xyz) 8 | [![stability-beta](https://img.shields.io/badge/stability-beta-33bbff.svg)](https://github.com/simzero-oss/cfd-xyz/releases) 9 | [![Join Slack](https://img.shields.io/badge/Join%20us%20on-Slack-e01563.svg)](https://join.slack.com/t/cfd-xyz/shared_invite/zt-15qjacmzo-1woWqeklQ0IeXZb_F6ueaQ) 10 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/simzero-oss/cfd-xyz/blob/main/LICENSE) 11 | [![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) 12 | 13 | [cfd.xyz](http://cfd.xyz) is an open-source web app to efficiently and easily explore fluid dynamics problems for a wide range of parameters. The framework provides a proof of technology for OpenFOAM tutorials, showing the whole process from the generation of the surrogate models to the web browser. It also includes a standalone web tool for visualizing users' models by directly dragging and dropping the output folder of the ROM offline stage. Beyond the current proof of technology, this enables a collaborative effort for the implementation of OpenFOAM-based surrogate models in applications demanding real-time solutions such as digital twins and other digital transformation technologies. 14 | 15 | We aim with the developments presented in this work to create a common place where canonical and industrial CFD problems can be visualized and analyzed without carrying out a simulation, or as a preliminary step for optimizing parameters of new simulations. Having an open-source centralized service has several advantages from educational, optimization and reproducibility point of views. But also from a CO2 footprint perspective. 16 | 17 | The web app relies on the [rom.js](https://github.com/simzero-oss/rom-js) module, a JavaScript port of a set of open-source packages (Eigen, Splinter and VTK/C++, ITHACA-FV) to solve the online stage of reduced-order models (ROM) generated by the ITHACA-FV tool. It can also be executed outside a web browser within a backend JavaScript runtime environment, or in a given web solution. 18 | 19 | 20 | This is a beta version, please handle it with care. Further features, optimizations and fixes are expected. We are also working on including machine learning data-driven methods. Contact us or join the [Slack channel](https://join.slack.com/t/cfd-xyz/shared_invite/zt-12uquswo6-FFVy95vRjfMF~~t8j~UBHA) if you want to collaborate. 21 | 22 | ### Requirements 23 | 24 | * [Docker](https://www.docker.com/get-started) 20.10.12 25 | * npm 6.14.11 (optional) 26 | 27 | ## Installation 28 | 29 | You can install and serve `cfd-xyz` in your computer with `npm`: 30 | 31 | ``` 32 | make all 33 | ``` 34 | 35 | And use the web by entering `http://localhost:3000` in your browser. 36 | 37 | Alternatively, you can use the [Docker image](https://github.com/orgs/simzero-oss/packages/container/package/cfd-xyz) for building and serving the web: 38 | 39 | ``` 40 | make all-docker 41 | ``` 42 | 43 | The web will be accessible at `http://localhost:5000`. 44 | 45 | ## Development 46 | 47 | The web app reads data from the `public/surrogates` folder for the interactive visualization. The instructions above install the data automatically but you can copy and paste the `surrogates` folder generated by [rom.js](https://github.com/simzero-oss/rom-js). 48 | 49 | ## Contributing 50 | 51 | Everyone is welcome to contribute to this project. See [CONTRIBUTING.md](https://github.com/simzero-oss/cfd-xyz/blob/main/CONTRIBUTING.md) for further details. 52 | 53 | cfd.xyz is a self-funded initiative, free of charge, with no adds, no popups, no registration and no data collection. 54 | 55 | ## Citations 56 | 57 | - Article published in the OpenFOAM® Journal: 58 | 59 | ``` 60 | @article{Pena-Monferrer_Diaz-Marin_2022, 61 | author={Peña-Monferrer, Carlos and Diaz-Marin, Carmen}, 62 | title={rom.js/cfd.xyz: An open-source framework for generating and visualizing parametric {CFD} results}, 63 | journal={OpenFOAM® Journal}, 64 | volume={2}, 65 | month={Oct.}, 66 | pages={143–148} 67 | DOI={10.51560/ofj.v2.83}, 68 | url={https://journal.openfoam.com/index.php/ofj/article/view/83}, 69 | year={2022}, 70 | } 71 | ``` 72 | 73 | - Web: 74 | ``` 75 | @online{cfd_xyz_web_2022, 76 | author={{SIMZERO}}, 77 | title={{cfd.xyz}}, 78 | howpublished={\url{https://cfd-xyz}}, 79 | addendum="(accessed: 28.04.2022)", 80 | } 81 | ``` 82 | 83 | - Repository: 84 | ``` 85 | @online{cfd_xyz_repo_2022, 86 | author={{SIMZERO}}, 87 | title={{cfd.xyz}}, 88 | howpublished={\url{https://github.com/simzero-oss/cfd-xyz-viewer}}, 89 | addendum="(accessed: 28.04.2022)", 90 | } 91 | ``` 92 | 93 | - Specific version with DOI. Example for v1.0.0-rc.8: 94 | ``` 95 | @software{cfd_xyz_v1.0.0-rc.8, 96 | author={{SIMZERO}}, 97 | title={simzero-oss/cfd-xyz}, 98 | month={mar}, 99 | year={2022}, 100 | publisher={Zenodo}, 101 | version={v1.0.0-rc.8}, 102 | doi={10.5281/zenodo.6365615}, 103 | url={https://doi.org/10.5281/zenodo.6365615} 104 | } 105 | ``` 106 | 107 | ## License 108 | 109 | Code on this repository is covered by the MIT license. All the media/images in the `public` directory are CC BY 4.0 except the `public/constructionSolver.png` image that is covered by CC0, and the cfd.xyz logos (`src/components/Main/logo*.svg`) with CC BY-ND 4.0 license so you may not alter, remix or transform these images. The cfd.xyz logo, SIMZERO and OpenFOAM are trademarks. A full description of the licenses can be found below: 110 | 111 | * Code: [MIT](https://github.com/simzero-oss/cfd-xyz/blob/main/LICENSE) 112 | * Media `public/constructionSolver.png`: [CC0](https://github.com/simzero-oss/cfd-xyz/blob/main/LICENSE-CC-0) 113 | * Media `src/components/Main/logoLight.svg` and `src/components/Main/logoDark.svg`: [CC BY-ND 4.0](https://github.com/simzero-oss/cfd-xyz/blob/main/LICENSE-CC-BY-ND) 114 | * Other media: [CC BY 4.0](https://github.com/simzero-oss/cfd-xyz/blob/main/LICENSE-CC-BY) 115 | 116 | * Trademarks: 117 | - OPENFOAM® is a registered trade mark of OpenCFD Limited, producer and distributor of the OpenFOAM software via [www.openfoam.com](www.openfoam.com). 118 | - cfd.xyz logo and SIMZERO are exclusive trademarks. Their use is only allowed in the context of this web app and in compliance with trademark law. Adaptations or modifications of the cfd.xyz logo are not permitted. 119 | -------------------------------------------------------------------------------- /babel-plugin-macros.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'fontawesome-svg-core': { 3 | 'license': 'free' 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfd-xyz", 3 | "license": "MIT", 4 | "version": "1.1.0", 5 | "author": "Carlos Pena-Monferrer ", 6 | "description": "An open-source web platform for data-driven generation and visualization of CFD data", 7 | "dependencies": { 8 | "@babel/helper-module-imports": "7.18.6", 9 | "@emotion/react": "11.10.4", 10 | "@emotion/styled": "11.10.4", 11 | "@firebase/app": "0.7.33", 12 | "@firebase/firestore": "3.5.0", 13 | "@firebase/storage": "0.9.9", 14 | "@fontsource/varela": "4.5.9", 15 | "@fortawesome/fontawesome-svg-core": "6.2.0", 16 | "@fortawesome/free-brands-svg-icons": "6.2.0", 17 | "@fortawesome/free-regular-svg-icons": "6.2.0", 18 | "@fortawesome/free-solid-svg-icons": "6.2.0", 19 | "@fortawesome/react-fontawesome": "0.2.0", 20 | "@kitware/vtk.js": "25.8.5", 21 | "@mui/icons-material": "5.10.6", 22 | "@mui/material": "5.10.7", 23 | "@mui/styles": "5.10.7", 24 | "@simzero/rom": "1.1.0", 25 | "ajv": "8.11.0", 26 | "arraybuffer-loader": "1.0.8", 27 | "babel-loader": "8.2.5", 28 | "babel-plugin-macros": "3.1.0", 29 | "babel-plugin-syntax-dynamic-import": "6.18.0", 30 | "buffer": "6.0.3", 31 | "crypto-browserify": "3.12.0", 32 | "crypto-js": "4.1.1", 33 | "eslint": "8.24.0", 34 | "exports-loader": "4.0.0", 35 | "file-loader": "6.2.0", 36 | "hex-rgb": "5.0.0", 37 | "jszip": "3.10.1", 38 | "jszip-utils": "0.1.0", 39 | "linkify-react": "4.0.2", 40 | "lodash": "4.17.21", 41 | "node-polyfill-webpack-plugin": "2.0.1", 42 | "papaparse": "5.3.2", 43 | "path-browserify": "1.0.1", 44 | "react": "17.0.2", 45 | "react-device-detect": "2.2.2", 46 | "react-dom": "17.0.2", 47 | "react-flippy": "1.1.0", 48 | "react-image": "4.0.3", 49 | "react-mui-dropzone": "4.0.6", 50 | "react-promise-loader": "1.2.0", 51 | "react-promise-tracker": "2.1.0", 52 | "react-router-dom": "6.4.1", 53 | "react-spinners": "0.13.4", 54 | "react-swipeable": "7.0.0", 55 | "serve": "14.0.1", 56 | "styled-components": "5.3.6", 57 | "typescript": "4.8.4", 58 | "use-window-orientation": "1.0.3", 59 | "webpack": "5.74.0", 60 | "webpack-cli": "4.10.0", 61 | "wslink": "1.8.2" 62 | }, 63 | "devDependencies": { 64 | "eslint-config-react-app": "7.0.1", 65 | "react-scripts": "5.0.1" 66 | }, 67 | "scripts": { 68 | "bundle": "webpack --mode production", 69 | "dev": "react-scripts start", 70 | "start": "serve -s build", 71 | "build": "react-scripts build", 72 | "test": "react-scripts test", 73 | "eject": "react-scripts eject" 74 | }, 75 | "proxy": "http://localhost:3000", 76 | "eslintConfig": { 77 | "extends": [ 78 | "react-app", 79 | "react-app/jest" 80 | ] 81 | }, 82 | "browser": { 83 | "crypto": false, 84 | "fs": false, 85 | "path": false, 86 | "os": false 87 | }, 88 | "browserslist": { 89 | "production": [ 90 | ">0.2%", 91 | "not dead", 92 | "not op_mini all" 93 | ], 94 | "development": [ 95 | "last 1 chrome version", 96 | "last 1 firefox version", 97 | "last 1 safari version" 98 | ] 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/favicon.ico -------------------------------------------------------------------------------- /public/images/OF/OF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/OF.png -------------------------------------------------------------------------------- /public/images/OF/combustion/combustion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/combustion/combustion.png -------------------------------------------------------------------------------- /public/images/OF/compressible/compressible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/compressible/compressible.png -------------------------------------------------------------------------------- /public/images/OF/heatTransfer/heatTransfer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/heatTransfer/heatTransfer.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/incompressible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/incompressible.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/simpleFoam/airFoil2D/airFoil2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/simpleFoam/airFoil2D/airFoil2D.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/simpleFoam/backwardFacingStep2D/backwardFacingStep2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/simpleFoam/backwardFacingStep2D/backwardFacingStep2D.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/simpleFoam/bump2D/bump2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/simpleFoam/bump2D/bump2D.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/simpleFoam/mixerVessel2D/mixerVessel2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/simpleFoam/mixerVessel2D/mixerVessel2D.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/simpleFoam/motorBike/motorBike.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/simpleFoam/motorBike/motorBike.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/simpleFoam/pitzDaily/pitzDaily.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/simpleFoam/pitzDaily/pitzDaily.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/simpleFoam/simpleFoam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/simpleFoam/simpleFoam.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/simpleFoam/turbineSiting/turbineSiting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/simpleFoam/turbineSiting/turbineSiting.png -------------------------------------------------------------------------------- /public/images/OF/incompressible/simpleFoam/windAroundBuildings/windAroundBuildings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/incompressible/simpleFoam/windAroundBuildings/windAroundBuildings.png -------------------------------------------------------------------------------- /public/images/OF/lagrangian/lagrangian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/lagrangian/lagrangian.png -------------------------------------------------------------------------------- /public/images/OF/multiphase/multiphase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/OF/multiphase/multiphase.png -------------------------------------------------------------------------------- /public/images/Tools/ITHACA-FV/ITHACA-FV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/Tools/ITHACA-FV/ITHACA-FV.png -------------------------------------------------------------------------------- /public/images/Tools/Tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/Tools/Tools.png -------------------------------------------------------------------------------- /public/images/Tools/VTK/VTK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/Tools/VTK/VTK.png -------------------------------------------------------------------------------- /public/images/card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/card.png -------------------------------------------------------------------------------- /public/images/constructionSolver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/public/images/constructionSolver.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 39 | CFD surrogate models on the web 40 | 41 | 42 | 43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "cfd.xyz", 3 | "name": "cfd.xyz", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { makeStyles } from "@mui/styles"; 6 | import { lightTheme, darkTheme } from './components/theme'; 7 | import { React, useState, useEffect, createContext } from "react"; 8 | import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; 9 | import { 10 | Navigation, 11 | Footer, 12 | Home, 13 | About, 14 | Error, 15 | OF, 16 | Incompressible, 17 | SimpleFoam, 18 | PitzDaily, 19 | Bump2D, 20 | MixerVessel2D, 21 | MotorBike, 22 | TurbineSiting, 23 | WindAroundBuildings, 24 | Tools, 25 | Steady, 26 | Slicer, 27 | } from "./components"; 28 | 29 | export const ThemeContext = createContext({ 30 | name: "light", 31 | setName: () => {} 32 | }); 33 | 34 | function App() { 35 | 36 | useEffect(() => { 37 | document.title = "cfd.xyz" 38 | }, []); 39 | 40 | const themeType = window.localStorage.getItem('theme') || "light" 41 | const theme = themeType === 'light' ? lightTheme : darkTheme; 42 | const useStyles = makeStyles(theme); 43 | const classes = useStyles(); 44 | const [name, setName] = useState(null); 45 | const value = {name, setName}; 46 | 47 | return ( 48 |
49 | 50 |
51 | 52 | 53 | 54 | } /> 55 | } /> 56 | } /> 57 | } /> 58 | } /> 59 | } /> 60 | } /> 61 | } /> 62 | } /> 63 | } /> 64 | } /> 65 | } /> 66 | } /> 67 | } /> 68 | } status={404} /> 69 | 70 |
71 | 72 |
73 |
74 |
75 | ); 76 | } 77 | 78 | export default App; 79 | -------------------------------------------------------------------------------- /src/components/Main/About.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import Box from '@mui/material/Box'; 3 | import Grid from '@mui/material/Grid'; 4 | import { makeStyles } from '@mui/styles'; 5 | import { lightTheme, darkTheme } from './../theme'; 6 | 7 | function About() { 8 | useEffect(() => { 9 | document.title = "About" 10 | }, []); 11 | 12 | const localTheme = window.localStorage.getItem('theme') || "light"; 13 | const theme = localTheme === 'light' ? lightTheme : darkTheme; 14 | const useStyles = makeStyles(theme); 15 | const classes = useStyles(); 16 | 17 | return ( 18 |
19 | 20 | 25 | 26 |
32 | The Web app 33 |
34 |
43 | cfd.xyz is an open-source React web app to efficiently and easily 44 | explore fluid dynamics problems for a wide range of parameters. 45 | The framework provides a proof of technology for OpenFOAM tutorials, 46 | showing the whole process from the generation of the surrogate 47 | models to the web browser. It also includes a standalone web tool 48 | for visualizing users' surrogate models by directly dragging and 49 | dropping the output folder of the ROM offline stage. Beyond the 50 | current proof of technology, this enables a collaborative effort 51 | for the implementation of OpenFOAM-based models in applications 52 | demanding real-time solutions such as digital twins and other 53 | digital transformation technologies. 54 |
55 |
64 | With this development, we aim to create a shared space where 65 | canonical and industrial computational fluid dynamics (CFD) 66 | problems can be visualized and analyzed without carrying out a 67 | simulation, or as a preliminary step for optimizing parameters of 68 | new simulations. Having an open-source centralized service has 69 | several advantages, not only from an educational, optimization and 70 | reproducibility point of view but also from a CO2 footprint 71 | perspective. 72 |
73 |
82 | The web app relies on the rom.js module, a JavaScript port of a set 83 | of open-source packages to solve the online stage of reduced-order 84 | models (ROM) generated by the ITHACA-FV tool. It can also be 85 | executed outside a web browser within a backend JavaScript runtime 86 | environment. Please visit and support the open-source packages used 87 | in this work: 88 | 93 | {' OpenFOAM'} 94 | , 95 | 100 | {' ITHACA-FV'} 101 | , 102 | 107 | {' Kitware'} 108 | , 109 | 114 | {' Eigen'} 115 | , 116 | 121 | {' Splinter'} 122 | , 123 | 128 | {' Emscripten'} 129 | , 130 | 134 | {' MUI'} 135 | , 136 | 141 | { ' React'} 142 | , 143 | and many others. You'll find a list of all the packages in the code 144 | repositories. 145 |
146 |
155 | This is a beta version, please handle with care. Further 156 | features, optimizations and fixes are expected. 157 |
158 |
173 |
3D view control keys:
174 |
   * Rotate: left click
175 |
   * Pan: shift + left click
176 |
   * Spin: Ctrl/Alt + left click
177 |
   * Zoom: mouse wheel
178 |
179 |
182 | The Code 183 |
184 |
190 | cfd.xyz is an open-source web app. You can install it locally, 191 | fix bugs or add new features at the 192 | 197 | {' cfd.xyz '} 198 | 199 | or 200 | 205 | {' rom-js '} 206 | 207 | GitHub repositories. Everyone is welcome to contribute to this 208 | project. 209 |
210 |
213 | The Licenses and trademarks 214 |
215 |
219 |
228 | cfd.xyz code and images (excluding the logo) are mainly covered 229 | by 230 | 235 | {' MIT '} 236 | 237 | and 238 | 243 | {' CC BY 4.0 '} 244 | 245 | licenses, respectively. Further details about the licenses can be 246 | found at 247 | 252 | {' cfd.xyz licenses'} 253 | . 254 | You can reuse this code under the terms of these licenses. 255 | Please cite this website and related repositories to help us to 256 | build more assets. 257 |
258 |
267 | cfd.xyz and SIMZERO are exclusive trademarks. Their use is only 268 | allowed in the context of this web app and in compliance with 269 | trademark law. Adaptations or modifications of the cfd.xyz logo 270 | are not permitted. 271 |
272 |
281 | This offering is not approved or endorsed by OpenCFD Limited, 282 | producer and distributor of the OpenFOAM software via 283 | www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® 284 | trade marks. 285 |
286 |
287 |
290 | The Authors 291 |
292 |
303 | cfd.xyz is developed and maintained by 304 | 309 | {' SIMZERO®'} 310 | . 311 | Please feel free to contact us by email (info@simzero.com) or 312 | joining the 313 | 318 | {' Slack channel'} 319 | . 320 |
321 |
324 | The Funding 325 |
326 |
337 | cfd.xyz is free of charge, with no ads, popups, 338 | registration or personal data collection. 339 |
340 |
351 | This is a self-funded initiative. If you like the tool and the 352 | mission and want to help with new developments and server costs 353 | please 354 | 359 | {' donate '} 360 | 361 | (PayPal). 362 |
363 |
366 | The Terms and conditions 367 |
368 |
379 | You agree that you use the site and the content at your own risk, 380 | and understand that this service is provided to you on an "AS IS" 381 | and "AS AVAILABLE" basis. The service is provided without 382 | warranties of any kind, including but not limited to content 383 | accuracy, reliability or completeness. We shall not be subject 384 | to liability for truth, accuracy or completeness of any information 385 | conveyed to the user. If your use of the site or the content 386 | results in the need for servicing, or replacing equipment or data, 387 | we shall not be responsible for those costs. 388 |
389 |
390 |
391 |
392 |
393 | ); 394 | } 395 | 396 | export default About; 397 | -------------------------------------------------------------------------------- /src/components/Main/Error.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import Box from '@mui/material/Box'; 3 | import Grid from '@mui/material/Grid'; 4 | import { makeStyles } from '@mui/styles'; 5 | import { lightTheme, darkTheme } from './../theme'; 6 | 7 | function Error() { 8 | useEffect(() => { 9 | document.title = "About" 10 | }, []); 11 | 12 | const localTheme = window.localStorage.getItem('theme') || "light"; 13 | const theme = localTheme === 'light' ? lightTheme : darkTheme; 14 | const useStyles = makeStyles(theme); 15 | const classes = useStyles(); 16 | 17 | return ( 18 |
19 | 20 | 25 | 404 PAGE NOT FOUND 26 | 27 | 28 |
29 | ); 30 | } 31 | 32 | export default Error; 33 | -------------------------------------------------------------------------------- /src/components/Main/Fader.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react' 2 | import { makeStyles } from '@mui/styles'; 3 | import Linkify from 'linkify-react'; 4 | import { global } from '../theme'; 5 | 6 | const Fader = ({ text }) => { 7 | const useStyles = makeStyles(global); 8 | const classes = useStyles(); 9 | 10 | const [fade, setFade] = useState(true); 11 | const [counter, setCounter] = useState(0); 12 | 13 | useEffect(() => { 14 | const timeout = setInterval(() => { 15 | if (fade) 16 | { 17 | setFade(false) 18 | } 19 | else 20 | { 21 | setFade(true) 22 | } 23 | if (counter < text.length - 1) 24 | { 25 | setCounter(counter+1) 26 | } 27 | else 28 | { 29 | setCounter(0) 30 | } 31 | }, 9000); 32 | return () => clearInterval(timeout) 33 | }, [fade]) 34 | 35 | return ( 36 |
37 | 44 | {text[counter]} 45 | 46 |
47 | ) 48 | } 49 | 50 | export default Fader 51 | -------------------------------------------------------------------------------- /src/components/Main/Footer.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import React from 'react'; 6 | import { makeStyles } from "@mui/styles"; 7 | import Typography from '@mui/material/Typography'; 8 | import Link from '@mui/material/Link'; 9 | import { lightTheme, darkTheme } from './../theme'; 10 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 11 | import { solid, brands } from '@fortawesome/fontawesome-svg-core/import.macro' 12 | 13 | const slackInvite = 'zt-15qjacmzo-1woWqeklQ0IeXZb_F6ueaQ' 14 | const slackLink = 'https://join.slack.com/t/cfd-xyz/shared_invite/' + slackInvite 15 | const linkedinLink = 'https://www.linkedin.com/sharing/share-offsite/?url=http://www.cfd.xyz' 16 | const paypalLink = 'https://www.paypal.com/donate/?hosted_button_id=KKB4LH96E59A4' 17 | 18 | function Footer() { 19 | const themeType = window.localStorage.getItem('theme') || 'light' 20 | 21 | //const localTheme = window.localStorage.getItem('theme'); 22 | const theme = themeType === 'light' ? lightTheme : darkTheme; 23 | const mainPrimaryColor = theme.palette.primary1Color; 24 | const mainSecondaryColor = theme.palette.primary2Color; 25 | const useStyles = makeStyles(theme); 26 | const classes = useStyles(); 27 | 28 | function Copyright() { 29 | return ( 30 |
31 | 38 | {'© '} 39 | {new Date().getFullYear()} 40 | {' '} 41 | 48 | {'SIMZERO'} 49 | 50 | 51 |
52 | ); 53 | } 54 | 55 | return ( 56 |
57 |
58 | 199 |
200 |
201 | ); 202 | } 203 | 204 | export default Footer; 205 | -------------------------------------------------------------------------------- /src/components/Main/Navigation.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { useEffect, useState } from "react"; 6 | import AppBar from "@mui/material/AppBar"; 7 | import { makeStyles } from "@mui/styles"; 8 | import Toolbar from '@mui/material/Toolbar'; 9 | import IconButton from '@mui/material/IconButton'; 10 | import { 11 | Link, 12 | useLocation, 13 | useNavigate, 14 | useParams 15 | } from "react-router-dom"; 16 | import LightModeIcon from '@mui/icons-material/WbSunny'; 17 | import DarkModeIcon from '@mui/icons-material/Brightness2'; 18 | import { lightTheme, darkTheme, navTheme } from './../theme'; 19 | import { useDarkMode } from './useDarkMode'; 20 | import logoLight from "./logoLight.svg"; 21 | import logoDark from "./logoDark.svg"; 22 | import {isMobile} from 'react-device-detect'; 23 | import { NavLink } from "react-router-dom"; 24 | 25 | // TODO: fix 26 | function withRouter(Component) { 27 | function ComponentWithRouterProp(props) { 28 | let location = useLocation(); 29 | let navigate = useNavigate(); 30 | let params = useParams(); 31 | return ( 32 | 36 | ); 37 | } 38 | 39 | return ComponentWithRouterProp; 40 | } 41 | 42 | function Navigation(element) { 43 | const useStyles = makeStyles(navTheme); 44 | const classes = useStyles(); 45 | const [theme, toggleTheme] = useDarkMode(); 46 | const [show, setShow] = useState(true); 47 | const theme2 = window.localStorage.getItem('theme') || 'light' 48 | const themeMode = theme2 === 'light' ? lightTheme : darkTheme; 49 | const icon = theme2 === 'light' ? : ; 50 | const logo = theme2 === 'light' ? logoLight : logoDark; 51 | const titleLight = 'Lights off'; 52 | const titleDark = 'Lights on'; 53 | const iconTitle = theme2 === 'light' ? titleLight : titleDark; 54 | const mainSecondaryColor = themeMode.palette.primary2Color; 55 | const controlToolbar = () => { 56 | if (window.scrollY > 100) { 57 | setShow(false) 58 | } 59 | else 60 | { 61 | setShow(true) 62 | } 63 | } 64 | 65 | useEffect(() => { 66 | window.addEventListener('scroll', controlToolbar) 67 | return () => { 68 | window.removeEventListener('scroll', controlToolbar) 69 | } 70 | }, []) 71 | 72 | const location = useLocation(); 73 | var location_path = location.pathname; 74 | 75 | if (location.pathname.match('/.*/$')) { 76 | location_path = location_path.slice(0, -1); 77 | } 78 | 79 | const split = location_path.split("/"); 80 | var title = []; 81 | var link = []; 82 | 83 | if ((location_path.length > 1) && (location_path != "/About")) { 84 | for (let i = 1; i < split.length; i++) { 85 | link += "/" + split[i]; 86 | if (!isMobile) { 87 | title.push(/{split[i]}); 88 | } 89 | } 90 | } 91 | 92 | return ( 93 |
94 | {show && 95 | 96 | 97 | 98 | cfd.xyz 99 | 100 |
101 | { title } 102 |
103 |
104 | 105 |
106 | {"About"} 107 |
108 |
109 |
110 | toggleTheme(theme)} 116 | > 117 | {icon} 118 | 119 |
120 |
121 | } 122 | 123 |
124 | ); 125 | } 126 | 127 | export default withRouter(Navigation); 128 | -------------------------------------------------------------------------------- /src/components/Main/ShowCards.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { React, useRef } from "react"; 6 | import { useSwipeable } from 'react-swipeable'; 7 | import Grid from '@mui/material/Grid' 8 | import Card from "@mui/material/Card"; 9 | import CardMedia from "@mui/material/CardMedia"; 10 | import Flippy, { FrontSide, BackSide } from 'react-flippy'; 11 | import { makeStyles } from "@mui/styles"; 12 | import { NavLink } from "react-router-dom"; 13 | import { lightTheme, darkTheme } from './../theme'; 14 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 15 | import { solid } from '@fortawesome/fontawesome-svg-core/import.macro' 16 | import SwipeIcon from '@mui/icons-material/Swipe'; 17 | import FiberNewIcon from '@mui/icons-material/FiberNew'; 18 | import PendingActionsIcon from '@mui/icons-material/PendingActions'; 19 | import {isMobile} from 'react-device-detect'; 20 | import Box from '@mui/material/Box'; 21 | import { createTheme } from '@mui/material/styles'; 22 | import Linkify from 'linkify-react'; 23 | import {Img} from 'react-image' 24 | import placeholder from './placeholder.png' 25 | 26 | const ShowCards = ({post}) => { 27 | const localTheme = window.localStorage.getItem('theme') || "light" 28 | const theme = localTheme === 'light' ? lightTheme : darkTheme; 29 | const newColor = localTheme === 'light' ? 'red' : 'white'; 30 | const useStyles = makeStyles(theme); 31 | const classes = useStyles(); 32 | const mainPrimaryColor = theme.palette.primary1Color; 33 | 34 | const inputRef = useRef([]); 35 | 36 | const handlers = useSwipeable({ 37 | onSwipedLeft: () => inputRef.current[post.title].toggle(), 38 | onSwipedRight: () => inputRef.current[post.title].toggle(), 39 | preventDefaultTouchmoveEvent: true, 40 | trackMouse: true 41 | }); 42 | 43 | function ShowBody() { 44 | return ( 45 | inputRef.current[post.title] = el} 49 | > 50 | 51 | {post.ready 52 | ? 53 | 54 | 60 | } 61 | className={classes.cardMedia} 62 | src={post.image + '.png'} 63 | /> 64 | 65 | : 66 | 72 | } 73 | className={classes.cardMedia} 74 | src={post.image + '.png'} 75 | /> 76 | } 77 | {post.surrogate === true && 78 |
79 | 88 |
89 | } 90 | {post.surrogate === false && 91 |
92 | 99 |
100 | } 101 | {post.new && 102 |
103 | 110 |
111 | } 112 | {post.ready 113 | ?
inputRef.current[post.title].toggle() } 115 | > 116 | {(inputRef.current && !isMobile ) && 117 | 126 | } 127 | {(inputRef.current && isMobile) && 128 | 135 | } 136 |
137 | : 138 |
inputRef.current[post.title].preventDefault() } 144 | > 145 | {(!isMobile) && 146 | 151 | } 152 |
153 | } 154 |
155 | {post.ready && 156 | 158 | {post.ready 159 | ?
161 | 169 | {post.description} 170 | 171 |
172 | : e.preventDefault()}> 173 |
175 | {post.description} 176 |
177 |
178 | } 179 |
inputRef.current[post.title].toggle() } 181 | > 182 | {(!isMobile) && 183 | 191 | } 192 |
193 |
194 | } 195 |
196 | ); 197 | } 198 | 199 | 200 | return ( 201 | 202 | 203 | {post.ready 204 | ?
205 | 206 |
207 | :
208 | 209 |
210 | } 211 | {post.ready 212 | ? 213 |
214 | {post.title} 215 |
216 |
217 | :
218 | 219 | {post.title} 220 | 221 |
222 | } 223 |
224 |
225 | ) 226 | } 227 | 228 | export default ShowCards; 229 | -------------------------------------------------------------------------------- /src/components/Main/index.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { useEffect } from "react"; 6 | import Grid from '@mui/material/Grid' 7 | import ShowCards from './ShowCards'; 8 | import { makeStyles } from "@mui/styles"; 9 | import posts from "./list"; 10 | import { global } from '../theme'; 11 | 12 | function Home() { 13 | useEffect(() => { 14 | document.title = "cfd.xyz" 15 | }, []); 16 | 17 | const useStyles = makeStyles(global); 18 | const classes = useStyles(); 19 | 20 | return ( 21 |
22 | 27 | {posts.map(post => ( 28 | 29 | ))} 30 | 31 |
32 | ); 33 | } 34 | 35 | export default Home; 36 | -------------------------------------------------------------------------------- /src/components/Main/list.js: -------------------------------------------------------------------------------- 1 | const posts = [ 2 | { 3 | title: "OpenFOAM Tutorials", 4 | link: "/OF", 5 | image: "/images/OF/OF", 6 | key: "1", 7 | ready: true, 8 | description: "Collection of OpenFOAM (www.openfoam.com) tutorials. OpenFOAM is a free, open source CFD software." 9 | }, 10 | 11 | { 12 | title: "Tools", 13 | link: "/Tools", 14 | image: "/images/Tools/Tools", 15 | key: "2", 16 | ready: true, 17 | description: "Standalone tools." 18 | }, 19 | 20 | { 21 | title: "Another solver", 22 | link: "none", 23 | image: "/images/constructionSolver", 24 | key: "3", 25 | ready: false, 26 | description: "Engage or contact us for adding your case or CFD solver." 27 | } 28 | ] 29 | 30 | export default posts; 31 | -------------------------------------------------------------------------------- /src/components/Main/logoDark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | R 30 | 31 | -------------------------------------------------------------------------------- /src/components/Main/logoLight.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | R 30 | 31 | -------------------------------------------------------------------------------- /src/components/Main/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simzero/cfd-xyz-viewer/0df9901ef4dd1672ed738d955ae70c6bbe484bff/src/components/Main/placeholder.png -------------------------------------------------------------------------------- /src/components/Main/useDarkMode.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { useContext, useState } from 'react'; 6 | import { ThemeContext } from "../../App.js"; 7 | 8 | export const useDarkMode = () => { 9 | const {setName} = useContext(ThemeContext); 10 | const [theme, setTheme] = useState("light"); 11 | const setMode = mode => { 12 | window.localStorage.setItem('theme', mode) 13 | setTheme(mode) 14 | }; 15 | 16 | const switchTheme = () => { 17 | theme === 'light' ? setMode('dark') : setMode('light') 18 | setName(theme) 19 | }; 20 | 21 | return [theme, switchTheme] 22 | }; 23 | -------------------------------------------------------------------------------- /src/components/Main/worker.js: -------------------------------------------------------------------------------- 1 | import {Buffer} from 'buffer'; 2 | import Papa from 'papaparse' 3 | import jszip from 'jszip' 4 | 5 | const transpose = (matrix) => { 6 | const transposed = matrix[0].map((col, i) => matrix.map(row => row[i])); 7 | 8 | const buffer = Float64Array.from(transposed.flat()); 9 | return buffer; 10 | } 11 | 12 | const loadData = async (zipFiles, filename) => { 13 | const item = zipFiles.files[filename]; 14 | const buffer = Buffer.from(await item.async('arrayBuffer')); 15 | const data = await readFile(buffer); 16 | 17 | return data; 18 | } 19 | 20 | const readFile = async (buffer) => { 21 | const decoder = new TextDecoder(); 22 | const decodedBuffer = decoder.decode(buffer); 23 | return new Promise(resolve => { 24 | Papa.parse(decodedBuffer, { 25 | download: false, 26 | delimiter: " ", 27 | dynamicTyping: true, 28 | skipEmptyLines: true, 29 | header: false, 30 | complete: results => { 31 | resolve(results.data); 32 | } 33 | }) 34 | }) 35 | }; 36 | 37 | onmessage = (e) => { 38 | let zipContent = e.data[0]; 39 | let stabilization = e.data[1]; 40 | let threeDimensions = e.data[2]; 41 | 42 | postMessage({event: "process", percent: 0}); 43 | 44 | (async () => { 45 | let zipFiles = await jszip.loadAsync(zipContent); 46 | zipContent = []; 47 | let zipKeys = Object.keys(zipFiles.files); 48 | 49 | postMessage({event: "process", percent: 10}); 50 | 51 | let BData = await loadData(zipFiles, 'B_mat.txt'); 52 | let KData = await loadData(zipFiles, 'K_mat.txt'); 53 | let coeffL2Data = await loadData(zipFiles, 'coeffL2_mat.txt'); 54 | 55 | let BTransposed = transpose(BData); 56 | let KTransposed = transpose(KData); 57 | 58 | let nPhiU = BData.length; 59 | let nPhiP = KData[0].length; 60 | let nPhiNut = coeffL2Data.length; 61 | let nRuns = coeffL2Data[0].length; 62 | 63 | postMessage({event: "constructor", nPhiU: nPhiU, nPhiP: nPhiP, nPhiNut, nRuns: nRuns}); 64 | postMessage({event: "process", percent: 20}); 65 | 66 | { 67 | let gridItem = zipFiles.files['internal.vtu']; 68 | let gridData = Buffer.from(await gridItem.async('arraybuffer')); 69 | 70 | postMessage( 71 | { 72 | event: "grid", 73 | grid: gridData 74 | }, 75 | [ 76 | gridData.buffer 77 | ] 78 | ); 79 | postMessage({event: "process", percent: 40}); 80 | } 81 | 82 | if (stabilization === "supremizer") { 83 | let PData = await loadData(zipFiles, 'P_mat.txt'); 84 | let PTransposed = transpose(PData); 85 | 86 | postMessage( 87 | { 88 | event: "matrices", 89 | P: PTransposed, 90 | K: KTransposed, 91 | B: BTransposed 92 | }, 93 | [ 94 | PTransposed.buffer, 95 | KTransposed.buffer, 96 | BTransposed.buffer 97 | ] 98 | ); 99 | } 100 | else if (stabilization === "PPE") { 101 | let DData = await loadData(zipFiles, 'D_mat.txt'); 102 | let BC3Data = await loadData(zipFiles, 'BC3_mat.txt'); 103 | 104 | let DTransposed = transpose(DData); 105 | let BC3Transposed = transpose(BC3Data); 106 | 107 | postMessage( 108 | { 109 | event: "matrices", 110 | D: DTransposed, 111 | K: KTransposed, 112 | B: BTransposed, 113 | BC3: BC3Transposed 114 | }, 115 | [ 116 | DTransposed.buffer, 117 | KTransposed.buffer, 118 | BTransposed.buffer, 119 | BC3Transposed.buffer, 120 | ] 121 | ); 122 | } 123 | else { 124 | // TODO: check 125 | } 126 | 127 | postMessage({event: "process", percent: 45}); 128 | 129 | let indexesU = [] 130 | for (let j = 0; j < nPhiU; j ++ ) { 131 | indexesU.push(j); 132 | } 133 | 134 | let indexesNut = [] 135 | for (let j = 0; j < nPhiNut; j ++ ) { 136 | indexesNut.push(j); 137 | } 138 | 139 | let indexesP = [] 140 | for (let j = 0; j < nPhiP; j ++ ) { 141 | indexesP.push(j); 142 | } 143 | 144 | { 145 | await Promise.all(indexesU.map(async (index) => { 146 | let Ct1Path = 'ct1_' + index + "_mat.txt"; 147 | let Ct1Data = await loadData(zipFiles, Ct1Path); 148 | let Ct1Transposed = transpose(Ct1Data); 149 | 150 | postMessage( 151 | { 152 | event: "Ct1", 153 | Ct1: Ct1Transposed 154 | }, 155 | [ 156 | Ct1Transposed.buffer 157 | ] 158 | ); 159 | })); 160 | postMessage({event: "process", percent: 50}); 161 | } 162 | 163 | { 164 | await Promise.all(indexesU.map(async (index) => { 165 | let Ct2Path = 'ct2_' + index + "_mat.txt"; 166 | let Ct2Data = await loadData(zipFiles, Ct2Path); 167 | let Ct2Transposed = transpose(Ct2Data); 168 | 169 | postMessage( 170 | { 171 | event: "Ct2", 172 | Ct2: Ct2Transposed 173 | }, 174 | [ 175 | Ct2Transposed.buffer 176 | ] 177 | ); 178 | })); 179 | postMessage({event: "process", percent: 55}); 180 | } 181 | 182 | { 183 | await Promise.all(indexesNut.map(async (indexNut) => { 184 | let weightsPath = 'wRBF_' + indexNut + '_mat.txt'; 185 | let weightsData = await loadData(zipFiles, weightsPath); 186 | let weightsTransposed = transpose(weightsData); 187 | 188 | postMessage( 189 | { 190 | event: "weights", 191 | index: indexNut, 192 | weights: weightsTransposed 193 | }, 194 | [ 195 | weightsTransposed.buffer 196 | ] 197 | ); 198 | })); 199 | postMessage({event: "process", percent: 60}); 200 | } 201 | 202 | { 203 | await Promise.all(indexesU.map(async (index) => { 204 | let CPath = 'C' + index + "_mat.txt" 205 | let CData = await loadData(zipFiles, CPath); 206 | let CTransposed = transpose(CData); 207 | 208 | postMessage( 209 | { 210 | event: "C", 211 | C: CTransposed 212 | }, 213 | [ 214 | CTransposed.buffer 215 | ] 216 | ); 217 | })); 218 | postMessage({event: "process", percent: 65}); 219 | } 220 | 221 | if (stabilization === "PPE") { 222 | { 223 | await Promise.all(indexesP.map(async (index) => { 224 | let GPath = 'G' + index + "_mat.txt" 225 | let GData = await loadData(zipFiles, GPath); 226 | let GTransposed = transpose(GData); 227 | 228 | postMessage( 229 | { 230 | event: "G", 231 | G: GTransposed 232 | }, 233 | [ 234 | GTransposed.buffer 235 | ] 236 | ); 237 | })); 238 | postMessage({event: "process", percent: 70}); 239 | } 240 | } 241 | 242 | { 243 | let muData = await loadData(zipFiles, 'par.txt'); 244 | let muTransposed = transpose(muData); 245 | let coeffL2Transposed = transpose(coeffL2Data); 246 | 247 | postMessage( 248 | { 249 | event: "RBF", 250 | mu: muTransposed, 251 | coeffL2: coeffL2Transposed 252 | }, 253 | [ 254 | muTransposed.buffer, 255 | coeffL2Transposed.buffer 256 | ] 257 | ); 258 | postMessage({event: "process", percent: 75}); 259 | } 260 | 261 | { 262 | let modesData = await loadData(zipFiles, 'EigenModes_U_mat.txt'); 263 | let modesTransposed = transpose(modesData); 264 | 265 | postMessage( 266 | { 267 | event: "modes", 268 | modes: modesTransposed 269 | }, 270 | [ 271 | modesTransposed.buffer 272 | ] 273 | ); 274 | postMessage({event: "process", percent: 90}); 275 | } 276 | 277 | { 278 | let vtpFile = zipKeys.filter((x) => [".vtp"].some(e => x.endsWith(e))); 279 | 280 | if (vtpFile != null && threeDimensions) { 281 | let vtpItem = zipFiles.files[vtpFile[0]]; 282 | let vtpData = Buffer.from(await vtpItem.async('arraybuffer')); 283 | 284 | postMessage( 285 | { 286 | event: "vtp", 287 | vtp: vtpData 288 | }, 289 | [ 290 | vtpData.buffer 291 | ] 292 | ); 293 | postMessage({event: "process", percent: 95}); 294 | } 295 | } 296 | 297 | zipFiles = []; 298 | postMessage({event: "process", percent: 100}); 299 | postMessage({event: "initialization", data: true}); 300 | })(); 301 | } 302 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/SimpleFoam/Bump2D.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { useEffect } from 'react'; 6 | import ROMView from './../../ROMView'; 7 | 8 | const surrogatesPath = '/surrogates'; 9 | 10 | // - Define case custom data 11 | const threeDimensions = false; 12 | const stabilization = "PPE"; 13 | const initialZoomPortrait = 20.0; 14 | const initialZoomLandscape = 145.0; 15 | const offsetY = -2.4; 16 | const dynamicTemperature = true; 17 | const initialTemperature = 20; 18 | const minTemperature = -50; 19 | const maxTemperature = 50; 20 | const stepTemperature = 5.0; 21 | const dynamicVelocity = true; 22 | const initialVelocity = 5.0; 23 | const minVelocity = 5.0; 24 | const maxVelocity = 70.0; 25 | const stepVelocity = 2.0; 26 | const dynamicAngle = false; 27 | const initialAngle = 0.0; 28 | const viewerLink = "/src/components/OF/Incompressible/SimpleFoam/Bump2D.jsx"; 29 | const ROMLink = "examples/OpenFOAM/incompressible/simpleFoam/bump2D"; 30 | // 31 | 32 | function Bump2D() { 33 | const casePath = window.location.pathname 34 | const caseName = casePath.split("/").pop(); 35 | const path = surrogatesPath + casePath 36 | 37 | useEffect(() => { 38 | document.title = casePath; 39 | }, []); 40 | 41 | return ( 42 |
43 | 66 |
67 | ); 68 | } 69 | 70 | export default Bump2D; 71 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/SimpleFoam/MixerVessel2D.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | import GenericView from './../../GenericView'; 4 | 5 | const simulationsPath = '/simulations'; 6 | 7 | // - Define case custom data 8 | const initialPlanesCoords = [0, 0, 0.005] 9 | const dataPath = "/simulations/OF/incompressible/simpleFoam/mixerVessel2D/"; 10 | const vtpVariable = "p"; 11 | const vtuVariable = "U"; 12 | const vtpTitle = "Pressure (m2/s2)"; 13 | const vtuTitle = "Velocity magnitude (m/s)"; 14 | const step = 0.0025; 15 | const codeLink = 'src/components/OF/Incompressible/SimpleFoam/MixerVessel2D.jsx'; 16 | // 17 | 18 | function MixerVessel2D() { 19 | const casePath = window.location.pathname; 20 | const caseName = casePath.split("/").pop(); 21 | const path = simulationsPath + casePath; 22 | 23 | useEffect(() => { 24 | document.title = "cfd.xyz | OF/incompressible/simpleFoam/mixerVessel2D" 25 | }, []); 26 | 27 | return ( 28 |
29 | 39 |
40 | ); 41 | } 42 | 43 | export default MixerVessel2D; 44 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/SimpleFoam/MotorBike.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | import GenericView from './../../GenericView'; 4 | 5 | const simulationsPath = '/simulations'; 6 | 7 | // - Define case custom data 8 | const initialPlanesCoords = [0, 0, 0.5] 9 | const dataPath = "/simulations/OF/incompressible/simpleFoam/motorBike/"; 10 | const vtpVariable = "p"; 11 | const vtuVariable = "U"; 12 | const vtpTitle = "Pressure (m2/s2)"; 13 | const vtuTitle = "Velocity magnitude (m/s)"; 14 | const step = 0.1; 15 | const codeLink = 'src/components/OF/Incompressible/SimpleFoam/MotorBike.jsx'; 16 | // 17 | 18 | function MotorBike() { 19 | const casePath = window.location.pathname; 20 | const caseName = casePath.split("/").pop(); 21 | const path = simulationsPath + casePath; 22 | 23 | useEffect(() => { 24 | document.title = "cfd.xyz | OF/incompressible/simpleFoam/motorBike" 25 | }, []); 26 | 27 | return ( 28 |
29 | 39 |
40 | ); 41 | } 42 | 43 | export default MotorBike; 44 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/SimpleFoam/PitzDaily.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { useEffect } from 'react'; 6 | import ROMView from './../../ROMView'; 7 | 8 | const surrogatesPath = '/surrogates'; 9 | 10 | // - Define case custom data 11 | const threeDimensions = false; 12 | const stabilization = "PPE"; 13 | const initialZoomPortrait = 0.55; 14 | const initialZoomLandscape = 1.3; 15 | const offsetY = 0.0; 16 | const dynamicTemperature = true; 17 | const initialTemperature = 20; 18 | const minTemperature = -100; 19 | const maxTemperature = 1000; 20 | const stepTemperature = 50.0; 21 | const dynamicVelocity = true; 22 | const initialVelocity = 1.0; 23 | const minVelocity = 1.0; 24 | const maxVelocity = 20.0; 25 | const stepVelocity = 1.0; 26 | const dynamicAngle = false; 27 | const initialAngle = 0.0; 28 | const viewerLink = "/src/components/OF/Incompressible/SimpleFoam/PitzDaily.jsx"; 29 | const ROMLink = "examples/OpenFOAM/incompressible/simpleFoam/pitzDaily"; 30 | // 31 | 32 | function PitzDaily() { 33 | const casePath = window.location.pathname 34 | const caseName = casePath.split("/").pop(); 35 | const path = surrogatesPath + casePath 36 | 37 | useEffect(() => { 38 | document.title = casePath; 39 | }, []); 40 | 41 | return ( 42 |
43 | 66 |
67 | ); 68 | } 69 | 70 | export default PitzDaily; 71 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/SimpleFoam/TurbineSiting.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | import GenericView from './../../GenericView'; 4 | 5 | const simulationsPath = '/simulations'; 6 | 7 | // - Define case custom data 8 | const initialPlanesCoords = [582135, 4785805, 960] 9 | const dataPath = "/simulations/OF/incompressible/simpleFoam/turbineSiting/"; 10 | const vtpVariable = "p"; 11 | const vtuVariable = "U"; 12 | const vtpTitle = "Pressure (m2/s2)"; 13 | const vtuTitle = "Velocity magnitude (m/s)"; 14 | const step = 10; 15 | const codeLink = 'src/components/OF/Incompressible/SimpleFoam/TurbineSiting.jsx'; 16 | // 17 | 18 | function TurbineSiting() { 19 | const casePath = window.location.pathname 20 | const caseName = casePath.split("/").pop(); 21 | const path = simulationsPath + casePath 22 | 23 | useEffect(() => { 24 | document.title = "/OF/incompressible/simpleFoam/turbineSiting" 25 | }, []); 26 | 27 | return ( 28 |
29 | 39 |
40 | ); 41 | } 42 | 43 | export default TurbineSiting; 44 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/SimpleFoam/WindAroundBuildings.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import ROMView from './../../ROMView'; 3 | 4 | const surrogatesPath = '/surrogates'; 5 | 6 | // - Define case custom data 7 | const threeDimensions = true; 8 | const initialStreamsCoords = [-20.0, 42.0, 10.0]; 9 | const initialPlanesCoords = [300.0, 150.0, 28.0]; 10 | const stepPlanes = 1.0; 11 | const stabilization = "PPE"; 12 | const initialZoomPortrait = 0.55; 13 | const initialZoomLandscape = 1.15; 14 | const offsetY = 10.0; 15 | const dynamicTemperature = false; 16 | const initialTemperature = 66.029869; 17 | const dynamicVelocity = false; 18 | const initialVelocity = 10.0; 19 | const dynamicAngle = true; 20 | const initialAngle = 0.0; 21 | const minAngle = -40.0; 22 | const maxAngle = 40.0; 23 | const stepAngle = 2.0; 24 | const viewerLink = "/src/components/OF/Incompressible/SimpleFoam/WindAroundBuildings.jsx"; 25 | const ROMLink = "examples/OpenFOAM/incompressible/simpleFoam/windAroundBuildings"; 26 | // 27 | 28 | function WindAroundBuildings() { 29 | const casePath = window.location.pathname 30 | const caseName = casePath.split("/").pop(); 31 | const repo = "https://raw.githubusercontent.com/simzero-oss/cfd-xyz-data/main/surrogates_v1.1.0/" 32 | // const path = surrogatesPath + casePath; 33 | const path = repo + casePath; 34 | 35 | useEffect(() => { 36 | document.title = "cfd.xyz | OF/incompressible/simpleFoam/windAroundBuildings" 37 | }, []); 38 | 39 | return ( 40 |
41 | 64 |
65 | ); 66 | } 67 | 68 | export default WindAroundBuildings; 69 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/SimpleFoam/index.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { React, useEffect } from "react"; 6 | import Grid from '@mui/material/Grid' 7 | import ShowCards from './../../../Main/ShowCards'; 8 | import { makeStyles } from "@mui/styles"; 9 | import posts from "./list"; 10 | import { global } from './../../../theme'; 11 | 12 | function SimpleFoam() { 13 | useEffect(() => { 14 | document.title = "/OF/incompressible/simpleFoam" 15 | }, []); 16 | 17 | const useStyles = makeStyles(global); 18 | const classes = useStyles(); 19 | 20 | return ( 21 |
22 | 27 | {posts.map(post => ( 28 | 29 | ))} 30 | 31 |
32 | ); 33 | } 34 | 35 | export default SimpleFoam; 36 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/SimpleFoam/list.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | const posts = [ 6 | { 7 | title: "pitzDaily", 8 | link: "/OF/incompressible/simpleFoam/pitzDaily", 9 | key: "1", 10 | ready: true, 11 | surrogate: true, 12 | new: false, 13 | image: "/images/OF/incompressible/simpleFoam/pitzDaily/pitzDaily", 14 | description: `Turbulent free shear layer forming a rearward-facing step. 15 | \nData: 16 | - P = 101325 Pa 17 | - T = [-100, 1000] °C 18 | - U_{inlet} = [1,20] m/s 19 | - Turb. model = kEpsilon 20 | - I_{inlet} = 5% 21 | \nDocs: 22 | - https://ntrs.nasa.gov/citations/19810023603 23 | ` 24 | }, 25 | 26 | { 27 | title: "bump2D", 28 | link: "/OF/incompressible/simpleFoam/bump2D", 29 | key: "3", 30 | ready: true, 31 | surrogate: true, 32 | new: false, 33 | image: "/images/OF/incompressible/simpleFoam/bump2D/bump2D", 34 | description: `Turbulent air flow in a channel with a bump (wall curvature). 35 | \nData: 36 | - P = 101325 Pa 37 | - T = [-100, 1000] °C 38 | - U_{inlet} = [5,100] m/s 39 | - Turb. model = kOmegaSST 40 | - k = 1.08e-03 m2/s2 41 | - omega = 5220.8 s-1 42 | \nDocs: 43 | - https://turbmodels.larc.nasa.gov/bump.html 44 | ` 45 | }, 46 | 47 | { 48 | title: "windAroundBuildings", 49 | link: "/OF/incompressible/simpleFoam/windAroundBuildings", 50 | key: "8", 51 | ready: true, 52 | surrogate: true, 53 | new: true, 54 | image: "/images/OF/incompressible/simpleFoam/windAroundBuildings/windAroundBuildings", 55 | description: `Wind around buildings.. 56 | \nData: 57 | - P = 101325 Pa 58 | - v = 1.5e-05 m2/s 59 | - U_{inlet} = 10 m/s 60 | - Uα_{inlet} = [-40,40] ° 61 | - Turb. model = kEpsilon 62 | - I_{inlet} = 10% 63 | ` 64 | }, 65 | 66 | { 67 | title: "airFoil2D", 68 | link: "/OF/incompressible/simpleFoam/airFoil2D", 69 | key: "2", 70 | ready: false, 71 | surrogate: false, 72 | new: false, 73 | image: "/images/OF/incompressible/simpleFoam/airFoil2D/airFoil2D", 74 | description: "Tutorial for a . \n\nData:\n -P = 101325 Pa \n -T = [-100, 1000] °C \n -U_{inlet} = [1,100] m/s \n -Turb. model = SpalartAllmaras" 75 | }, 76 | 77 | { 78 | title: "mixerVessel2D", 79 | link: "/OF/incompressible/simpleFoam/mixerVessel2D", 80 | key: "5", 81 | ready: true, 82 | surrogate: false, 83 | image: "/images/OF/incompressible/simpleFoam/mixerVessel2D/mixerVessel2D", 84 | description: `2D mixer vessel. 85 | \nVisualization of data from an OpenFOAM simulation. 86 | \nModel with ROM is pending for a multiple reference frame (MRF). See GitHub issue: https://github.com/simzero-oss/cfd-xyz/issues/1. 87 | ` 88 | }, 89 | 90 | { 91 | title: "motorBike", 92 | link: "/OF/incompressible/simpleFoam/motorBike", 93 | key: "6", 94 | ready: true, 95 | surrogate: false, 96 | new: false, 97 | image: "/images/OF/incompressible/simpleFoam/motorBike/motorBike", 98 | description: `Flow around a motorbike. 99 | \nVisualization of data from an OpenFOAM simulation. 100 | \nModel with ROM will be soon available. 101 | ` 102 | }, 103 | 104 | { 105 | title: "turbineSiting", 106 | link: "/OF/incompressible/simpleFoam/turbineSiting", 107 | key: "7", 108 | ready: true, 109 | surrogate: false, 110 | new: false, 111 | image: "/images/OF/incompressible/simpleFoam/turbineSiting/turbineSiting", 112 | description: `Flow around a turbine siting. 113 | \nVisualization of data from an OpenFOAM simulation. 114 | \nModel with ROM will be soon available. 115 | ` 116 | } 117 | 118 | ] 119 | 120 | export default posts; 121 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/index.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { React, useEffect } from "react"; 6 | import Grid from '@mui/material/Grid' 7 | import ShowCards from './../../Main/ShowCards'; 8 | import { makeStyles } from "@mui/styles"; 9 | import posts from "./list"; 10 | import { global } from './../../theme'; 11 | 12 | function Incompressible() { 13 | useEffect(() => { 14 | document.title = "/OF/incompressible" 15 | }, []); 16 | 17 | const useStyles = makeStyles(global); 18 | const classes = useStyles(); 19 | 20 | return ( 21 |
22 | 27 | {posts.map(post => ( 28 | 29 | ))} 30 | 31 |
32 | ); 33 | } 34 | 35 | export default Incompressible; 36 | -------------------------------------------------------------------------------- /src/components/OF/Incompressible/list.js: -------------------------------------------------------------------------------- 1 | const posts = [ 2 | { 3 | title: "simpleFoam", 4 | link: "/OF/incompressible/simpleFoam", 5 | image: "/images/OF/incompressible/simpleFoam/simpleFoam", 6 | key: "1", 7 | ready: true, 8 | description: "Steady-state solver for incompressible, turbulent flows." 9 | } 10 | ] 11 | 12 | export default posts; 13 | -------------------------------------------------------------------------------- /src/components/OF/index.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { React, useEffect } from "react"; 6 | import Grid from '@mui/material/Grid' 7 | import ShowCards from './../Main/ShowCards'; 8 | import { makeStyles } from "@mui/styles"; 9 | import posts from "./list"; 10 | import { global } from './../theme'; 11 | 12 | function OF() { 13 | useEffect(() => { 14 | document.title = "/OF" 15 | }, []); 16 | 17 | const useStyles = makeStyles(global); 18 | const classes = useStyles(); 19 | 20 | return ( 21 |
22 | 27 | {posts.map(post => ( 28 | 29 | ))} 30 | 31 |
32 | ); 33 | } 34 | 35 | export default OF; 36 | -------------------------------------------------------------------------------- /src/components/OF/list.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | const posts = [ 6 | { 7 | title: "incompressible", 8 | link: "/OF/incompressible", 9 | image: "/images/OF/incompressible/incompressible", 10 | key: "1", 11 | ready: true, 12 | description: "Incompressible flow tutorials for different solvers." 13 | }, 14 | 15 | { 16 | title: "compressible", 17 | link: "OF/compressible", 18 | image: "/images/OF/compressible/compressible", 19 | key: "2", 20 | ready: false, 21 | description: " " 22 | }, 23 | 24 | { 25 | title: "multiphase", 26 | link: "OF/multiphase", 27 | image: "/images/OF/multiphase/multiphase", 28 | key: "3", 29 | ready: false, 30 | description: " " 31 | }, 32 | 33 | { 34 | title: "heatTransfer", 35 | link: "OF/heatTransfer", 36 | image: "/images/OF/heatTransfer/heatTransfer", 37 | key: "4", 38 | ready: false, 39 | description: " " 40 | }, 41 | 42 | { 43 | title: "lagrangian", 44 | link: "OF/lagrangian", 45 | image: "/images/OF/lagrangian/lagrangian", 46 | key: "5", 47 | ready: false, 48 | description: " " 49 | }, 50 | 51 | { 52 | title: "combustion", 53 | link: "OF/combustion", 54 | image: "/images/OF/combustion/combustion", 55 | key: "6", 56 | ready: false, 57 | description: " " 58 | }, 59 | ] 60 | 61 | export default posts; 62 | -------------------------------------------------------------------------------- /src/components/Tools/ITHACA-FV/Steady.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import {Buffer} from 'buffer'; 6 | 7 | import { useState, useRef, useEffect } from 'react'; 8 | import Slider from '@mui/material/Slider'; 9 | import Box from '@mui/material/Box'; 10 | 11 | import Grid from '@mui/material/Grid' 12 | import TextField from '@mui/material/TextField' 13 | import Checkbox from '@mui/material/Checkbox' 14 | import FormGroup from '@mui/material/FormGroup' 15 | import FormControlLabel from '@mui/material/FormControlLabel' 16 | 17 | import { DropzoneAreaBase } from "react-mui-dropzone"; 18 | 19 | import { makeStyles } from '@mui/styles'; 20 | 21 | import hexRgb from 'hex-rgb'; 22 | 23 | import '@kitware/vtk.js/Rendering/Profiles/Geometry'; 24 | import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow'; 25 | import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor'; 26 | import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper'; 27 | import vtkXMLPolyDataReader from '@kitware/vtk.js/IO/XML/XMLPolyDataReader'; 28 | import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray'; 29 | import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps'; 30 | import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction'; 31 | import vtkScalarBarActor from '@kitware/vtk.js/Rendering/Core/ScalarBarActor'; 32 | import debounce from "lodash/debounce"; 33 | import { lightTheme, darkTheme } from './../../theme'; 34 | import rom from '@simzero/rom' 35 | import jszip from 'jszip' 36 | import JSZipUtils from 'jszip-utils' 37 | import Papa from 'papaparse' 38 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 39 | import { solid } from '@fortawesome/fontawesome-svg-core/import.macro' 40 | import PropagateLoader from "react-spinners/PropagateLoader"; 41 | 42 | const initialZoom = 1.3; 43 | 44 | const { ColorMode } = vtkMapper; 45 | 46 | var background = [255, 255, 255]; 47 | 48 | function Steady() { 49 | useEffect(() => { 50 | document.title = "cfd.xyz | Tools/ITHACA-FV_Steady" 51 | }, []); 52 | 53 | const vtkContainerRef = useRef(null); 54 | const context = useRef(null); 55 | const [dataLoaded, setDataLoaded] = useState(false); 56 | const [UFixed, setUFixed] = useState(false); 57 | const [nuFixed, setNuFixed] = useState(false); 58 | 59 | const localTheme = window.localStorage.getItem('theme') || "light"; 60 | const trackTheme = useState(window.localStorage.getItem('theme') || "light"); 61 | const theme = localTheme === 'light' ? lightTheme : darkTheme; 62 | const useStyles = makeStyles(theme); 63 | const classes = useStyles(); 64 | 65 | const mainColor = theme.checkbox.color; 66 | const textColorLoader = localTheme === 67 | 'light' ? lightTheme.bodyText.color : darkTheme.bodyText.color; 68 | 69 | let backgroundLight = hexRgb(lightTheme.body, {format: 'array'}); 70 | let backgroundDark = hexRgb(darkTheme.body, {format: 'array'}); 71 | backgroundLight = backgroundLight.map(x => x / 255); 72 | backgroundDark = backgroundDark.map(x => x / 255); 73 | backgroundLight.pop(); 74 | backgroundDark.pop(); 75 | 76 | let textColorLight = lightTheme.vtkText.color; 77 | let textColorDark = darkTheme.vtkText.color; 78 | 79 | const [files, setFiles] = useState([]); 80 | const [isConfirmed,setConfirmed] = useState(false); 81 | const [isDisabled,setDisabled] = useState(false); 82 | const [UMin, setUMin] = useState(1); 83 | const [UIni, setUIni] = useState(5); 84 | const [UMax, setUMax] = useState(10); 85 | const [nuMin, setNuMin] = useState(1e-06) 86 | const [nuIni, setNuIni] = useState(1e-05) 87 | const [nuMax, setNuMax] = useState(1e-04) 88 | const [velocityValue, setVelocityValue] = useState(); 89 | const [viscosityValue, setViscosityValue] = useState(); 90 | 91 | useEffect(() => { 92 | if (context.current) { 93 | const { scalarBarActor, renderer, renderWindow } = context.current; 94 | if (renderWindow) { 95 | const background = localTheme === 'light' ? backgroundLight : backgroundDark; 96 | const textColor = localTheme === 'light' ? textColorLight : textColorDark; 97 | 98 | const scalarBarActorStyle1 = { 99 | paddingBottom: 30, 100 | fontColor: textColor, 101 | fontStyle: 'normal', 102 | fontFamily: theme.vtkText.fontFamily 103 | }; 104 | 105 | renderer.setBackground(background); 106 | scalarBarActor.setAxisTextStyle(scalarBarActorStyle1); 107 | scalarBarActor.setTickTextStyle(scalarBarActorStyle1); 108 | scalarBarActor.modified(); 109 | renderWindow.modified(); 110 | renderWindow.render(); 111 | } 112 | } 113 | }, [trackTheme, localTheme, backgroundLight, backgroundDark]); 114 | 115 | 116 | useEffect(() => { 117 | if (context.current) { 118 | const { reduced } = context.current; 119 | const reader = vtkXMLPolyDataReader.newInstance(); 120 | const actor = vtkActor.newInstance(); 121 | const scalarBarActor = vtkScalarBarActor.newInstance(); 122 | const lookupTable = vtkColorTransferFunction.newInstance(); 123 | const mapper = vtkMapper.newInstance({ 124 | interpolateScalarsBeforeMapping: true, 125 | colorByArrayName: "uRec", 126 | colorMode: ColorMode.DEFAULT, 127 | scalarMode: 'pointData', 128 | useLookupTableScalarRange: true, 129 | lookupTable, 130 | }); 131 | actor.setMapper(mapper); 132 | mapper.setLookupTable(lookupTable); 133 | scalarBarActor.setVisibility(true); 134 | const mystyle = { 135 | margin: '0', 136 | padding: '0', 137 | paddingBottom: '50', 138 | position: 'absolute', 139 | top: '0', 140 | left: '0', 141 | width: '99%', 142 | height: '93%', 143 | overflow: 'hidden', 144 | }; 145 | const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ 146 | containerStyle: mystyle, 147 | background, 148 | rootContainer: vtkContainerRef.current, 149 | }); 150 | const renderer = fullScreenRenderer.getRenderer(); 151 | const renderWindow = fullScreenRenderer.getRenderWindow(); 152 | const preset = vtkColorMaps.getPresetByName('erdc_rainbow_bright'); 153 | lookupTable.setVectorModeToMagnitude(); 154 | lookupTable.applyColorMap(preset); 155 | lookupTable.updateRange(); 156 | let polydata; 157 | const scalarBarActorStyle = { 158 | paddingBottom: 30, 159 | fontColor: theme.vtkText.color, 160 | fontStyle: 'normal', 161 | fontFamily: theme.vtkText.fontFamily 162 | }; 163 | 164 | reduced.nu(nuIni*1e-05); 165 | reduced.solveOnline(UIni, 0.0); 166 | const polydata_string = reduced.unstructuredGridToPolyData(); 167 | // TODO: parse directly as buffer or parse as a string... 168 | var buf = Buffer.from(polydata_string, 'utf-8'); 169 | reader.parseAsArrayBuffer(buf); 170 | polydata = reader.getOutputData(0); 171 | 172 | renderer.addActor(scalarBarActor); 173 | renderer.addActor(actor); 174 | 175 | reduced.reconstruct(); 176 | const newU = reduced.geometry(); 177 | 178 | var nCells = polydata.getNumberOfPoints(); 179 | polydata.getPointData().setActiveScalars("uRec"); 180 | 181 | const array = vtkDataArray.newInstance({ 182 | name: 'uRec', 183 | size: nCells*3, 184 | numberOfComponents: 3, 185 | dataType: 'Float32Array' 186 | }); 187 | for (let i = 0; i < nCells; i++) { 188 | let v =[newU[i], newU[i + nCells], newU[i + nCells * 2]]; 189 | array.setTuple(i, v) 190 | } 191 | 192 | array.modified(); 193 | 194 | polydata.getPointData().addArray(array); 195 | 196 | var activeArray = polydata.getPointData().getArray("uRec"); 197 | const dataRange = [].concat(activeArray ? activeArray.getRange() : [0, 1]); 198 | lookupTable.setMappingRange(dataRange[0], dataRange[1]); 199 | lookupTable.updateRange(); 200 | mapper.setScalarModeToUsePointFieldData(); 201 | mapper.setScalarRange(dataRange[0],dataRange[1]); 202 | mapper.setColorByArrayName('uRec'); 203 | mapper.setInputData(polydata); 204 | scalarBarActor.setScalarsToColors(mapper.getLookupTable()); 205 | scalarBarActor.setAxisLabel("Velocity magnitude (m/s)"); 206 | scalarBarActor.setAxisTextStyle(scalarBarActorStyle); 207 | scalarBarActor.setTickTextStyle(scalarBarActorStyle); 208 | lookupTable.updateRange(); 209 | scalarBarActor.modified(); 210 | renderer.resetCamera(); 211 | renderer.getActiveCamera().zoom(initialZoom); 212 | renderWindow.render(); 213 | renderer.resetCameraClippingRange(); 214 | scalarBarActor.modified(); 215 | scalarBarActor.setVisibility(false); 216 | renderWindow.render(); 217 | renderWindow.modified(); 218 | scalarBarActor.modified(); 219 | scalarBarActor.setVisibility(true); 220 | 221 | const camera = renderer.getActiveCamera(); 222 | let focalPoint = [].concat(camera ? camera.getFocalPoint() : [0, 1, 2]); 223 | let cameraPosition = [].concat(camera ? camera.getPosition() : [0, 1, 2]); 224 | 225 | renderer.getActiveCamera().setPosition 226 | ( 227 | cameraPosition[0], 228 | cameraPosition[1], 229 | cameraPosition[2] 230 | ); 231 | renderer.getActiveCamera().setFocalPoint 232 | ( 233 | focalPoint[0], 234 | focalPoint[1], 235 | focalPoint[2] 236 | ); 237 | 238 | renderWindow.modified(); 239 | renderWindow.render(); 240 | 241 | context.current = { 242 | focalPoint, 243 | cameraPosition, 244 | reduced, 245 | reader, 246 | fullScreenRenderer, 247 | renderWindow, 248 | renderer, 249 | lookupTable, 250 | polydata, 251 | actor, 252 | scalarBarActor, 253 | mapper, 254 | }; 255 | setVelocityValue(UIni); 256 | setViscosityValue(nuIni); 257 | } 258 | }, [dataLoaded]); 259 | 260 | const patterns = [ 261 | '.*.zip' 262 | ]; 263 | 264 | function checkZip(item) { 265 | return item.file.name.match(patterns); 266 | } 267 | 268 | function checkAll(names) { 269 | //validFiles(); 270 | //const B_check = ["B_mat.txt"].includes(item.file.name) 271 | //console.log(B_check) 272 | } 273 | 274 | function clear() { 275 | setFiles([]); 276 | } 277 | 278 | const readFile = async (buffer) => { 279 | const csvData = buffer.toString(); 280 | 281 | return new Promise(resolve => { 282 | Papa.parse(csvData, { 283 | download: false, 284 | delimiter: " ", 285 | dynamicTyping: true, 286 | skipEmptyLines: true, 287 | header: false, 288 | complete: results => { 289 | resolve(results.data); 290 | } 291 | }) 292 | }) 293 | }; 294 | 295 | 296 | const loadData = async (zipFiles, filename) => { 297 | const item = zipFiles.files[filename] 298 | const buffer = Buffer.from(await item.async('arraybuffer')) 299 | const data = await readFile(buffer); 300 | const transposed = data[0].map((col, i) => data.map(row => row[i])); 301 | const transposedBuffer = Float64Array.from(transposed.flat()); 302 | 303 | return [transposedBuffer, data.length, data[0].length]; 304 | } 305 | 306 | useEffect(() => { 307 | return () => { 308 | if (context.current) { 309 | const { 310 | reduced, 311 | fullScreenRenderer, 312 | polydata, 313 | actor, 314 | scalarBarActor, 315 | mapper 316 | } = context.current; 317 | reduced.delete(); 318 | actor.delete(); 319 | scalarBarActor.delete(); 320 | mapper.delete(); 321 | polydata.delete(); 322 | fullScreenRenderer.delete(); 323 | context.current = null; 324 | } 325 | }; 326 | }, []); 327 | 328 | const confirmed = async() => { 329 | setNuMin(nuMin*1e05); 330 | setNuMax(nuMax*1e05); 331 | if (! UFixed) 332 | { 333 | const UMid = Number(UMin) + 0.5*(Number(UMax) - Number(UMin)); 334 | setUIni(UMid); 335 | } 336 | else 337 | { 338 | setUIni(UMin); 339 | } 340 | 341 | if (! nuFixed) 342 | { 343 | const nuMid = Number(nuMin) + 0.5*(Number(nuMax) - Number(nuMin)); 344 | setNuIni(nuMid*1e05); 345 | } 346 | else 347 | { 348 | setNuIni(Number(nuMin*1e05)); 349 | } 350 | 351 | let loadedNames = [] 352 | files.map((item) => 353 | loadedNames.push(item.file.name) 354 | ) 355 | 356 | const zipContent = await JSZipUtils.getBinaryContent(files[0].data); 357 | const zipFiles = await jszip.loadAsync(zipContent); 358 | const zipKeys = Object.keys(zipFiles.files); 359 | 360 | const isTurbulent = zipKeys.includes("coeffL2_mat.txt") 361 | 362 | checkAll(loadedNames); 363 | setConfirmed(true); 364 | 365 | await rom.ready 366 | 367 | const nBC = 2; 368 | 369 | const KData = await loadData(zipFiles, "K_mat.txt"); 370 | const BData = await loadData(zipFiles, "B_mat.txt"); 371 | const modesData = await loadData(zipFiles, 'EigenModes_U_mat.txt'); 372 | const coeffL2Data = await loadData(zipFiles, 'coeffL2_mat.txt'); 373 | const muData = await loadData(zipFiles, 'par.txt'); 374 | const gridItem = zipFiles.files['internal.vtu']; 375 | const gridData = Buffer.from(await gridItem.async('arraybuffer')); 376 | 377 | const nPhiU = BData[1]; 378 | const nPhiP = KData[2]; 379 | const nPhiNut = coeffL2Data[1]; 380 | const nRuns = coeffL2Data[2]; 381 | 382 | const reduced = new rom.reducedSteady(nPhiU + nPhiP, nPhiU + nPhiP); 383 | 384 | let stabilization = 'supremizer'; 385 | 386 | if (zipKeys.includes("D_mat.txt")) { 387 | stabilization = 'PPE'; 388 | } 389 | 390 | reduced.stabilization(stabilization); 391 | reduced.nPhiU(nPhiU); 392 | reduced.nPhiP(nPhiP); 393 | reduced.nPhiNut(nPhiNut); 394 | reduced.nRuns(nRuns); 395 | reduced.nBC(nBC); 396 | 397 | reduced.readUnstructuredGrid(gridData); 398 | reduced.initialize(); 399 | 400 | reduced.K().set(KData[0]); 401 | reduced.B().set(BData[0]); 402 | 403 | if (stabilization === "supremizer") { 404 | const PData = await loadData(zipFiles, 'P_mat.txt'); 405 | 406 | reduced.P().set(PData[0]); 407 | } 408 | else if (stabilization === "PPE") { 409 | const DData = await loadData(zipFiles, 'D_mat.txt'); 410 | const BC3Data = await loadData(zipFiles, 'BC3_mat.txt'); 411 | 412 | reduced.D().set(DData[0]); 413 | reduced.BC3().set(BC3Data[0]); 414 | } 415 | else { 416 | // TODO: check 417 | } 418 | 419 | reduced.modes().set(modesData[0]); 420 | 421 | let indexes = [] 422 | for (var i = 0; i < nPhiU; i++ ) { 423 | indexes.push(i); 424 | } 425 | 426 | await Promise.all(indexes.map(async (index) => { 427 | const CPath = 'C' + index + "_mat.txt" 428 | const CData = await loadData(zipFiles, CPath); 429 | 430 | reduced.C().set(CData[0]); 431 | reduced.addCMatrix(); 432 | })); 433 | 434 | if (stabilization === "PPE") { 435 | let indexesP = [] 436 | for (var j = 0; j < nPhiP; j ++ ) { 437 | indexesP.push(j); 438 | } 439 | 440 | await Promise.all(indexesP.map(async (index) => { 441 | const GPath = 'G' + index + "_mat.txt" 442 | const GData = await loadData(zipFiles, GPath); 443 | 444 | reduced.G().set(GData[0]); 445 | reduced.addGMatrix(); 446 | })); 447 | } 448 | 449 | if (isTurbulent) { 450 | // const coeffL2Data = await loadData(zipFiles, 'coeffL2_mat.txt'); 451 | 452 | let indexesNut = [] 453 | for (var j = 0; j < nPhiNut; j ++ ) { 454 | indexesNut.push(j); 455 | } 456 | 457 | await Promise.all(indexes.map(async (index) => { 458 | const C1Path = 'ct1_' + index + "_mat.txt" 459 | const C2Path = 'ct2_' + index + "_mat.txt" 460 | const C1Data = await loadData(zipFiles, C1Path); 461 | const C2Data = await loadData(zipFiles, C2Path); 462 | 463 | reduced.Ct1().set(C1Data[0]); 464 | reduced.addCt1Matrix(); 465 | reduced.Ct2().set(C2Data[0]); 466 | reduced.addCt2Matrix(); 467 | })); 468 | 469 | await Promise.all(indexesNut.map(async (indexNut) => { 470 | const weightsPath = 'wRBF_' + indexNut + '_mat.txt'; 471 | const weightsData = await loadData(zipFiles, weightsPath); 472 | 473 | reduced.weights().set(weightsData[0]); 474 | reduced.addWeights(); 475 | })); 476 | } 477 | 478 | reduced.mu().set(muData[0]); 479 | reduced.coeffL2().set(coeffL2Data[0]); 480 | reduced.setRBF(); 481 | 482 | context.current = { reduced }; 483 | setDataLoaded(true); 484 | } 485 | 486 | const resetCamera = () => { 487 | if (context.current) { 488 | const { 489 | fullScreenRenderer, 490 | focalPoint, 491 | cameraPosition, 492 | renderer, 493 | renderWindow 494 | } = context.current; 495 | renderer.getActiveCamera().setProjectionMatrix(null); 496 | renderer.resetCamera(); 497 | renderer.getActiveCamera().setPosition 498 | ( 499 | cameraPosition[0], 500 | cameraPosition[1], 501 | cameraPosition[2] 502 | ); 503 | renderer.getActiveCamera().setFocalPoint 504 | ( 505 | focalPoint[0], 506 | focalPoint[1], 507 | focalPoint[2] 508 | ); 509 | renderer.getActiveCamera().setViewUp(0.0, 1.0, 0.0) 510 | fullScreenRenderer.resize(); 511 | renderer.getActiveCamera().zoom(initialZoom); 512 | renderWindow.render(); 513 | } 514 | } 515 | 516 | function takeScreenshot() { 517 | if (context.current) { 518 | const { renderWindow } = context.current; 519 | renderWindow.captureImages()[0].then( 520 | (image) => { 521 | (async () => { 522 | const blob = await (await fetch(image)).blob(); 523 | var a = document.createElement("a"); 524 | a.innerHTML = 'download'; 525 | a.href = URL.createObjectURL(blob); 526 | a.download = "pitzDaily_nu_" + viscosityValue + ".png"; 527 | a.click(); 528 | })(); 529 | } 530 | ); 531 | } 532 | } 533 | 534 | function handleUFixed() { 535 | if (!UFixed) { 536 | setUMax(UMin); 537 | setVelocityValue(UMin); 538 | setUIni(UMin); 539 | } 540 | setUFixed(!UFixed) 541 | } 542 | 543 | function handleNuFixed() { 544 | if (!nuFixed) { 545 | setNuMax(nuMin); 546 | setViscosityValue(nuMin); 547 | setNuIni(nuMin); 548 | } 549 | setNuFixed(!nuFixed) 550 | } 551 | 552 | function restart() { 553 | // TODO: this is temporal 554 | window.location.reload(); 555 | } 556 | 557 | function downloadData() { 558 | if (context.current) { 559 | const { reduced } = context.current; 560 | const data_string = reduced.exportUnstructuredGrid(); 561 | var blob = new Blob([data_string], { 562 | type: 'text/plain' 563 | }); 564 | var a = document.createElement("a"); 565 | a.innerHTML = 'download'; 566 | a.href = URL.createObjectURL(blob); 567 | a.download = "pitzDaily_nu_" + viscosityValue + "_U_" + velocityValue + ".vtu"; 568 | a.click(); 569 | } 570 | } 571 | 572 | const myFunction = (eventSrcDesc, newValue) => { 573 | // console.log({ eventSrcDesc, newValue }); 574 | }; 575 | 576 | const handleViscosityChange = (event, newValue) => { 577 | setViscosityValue(newValue); 578 | stateDebounceMyFunction("slider-tate", newValue); 579 | }; 580 | 581 | const handleVelocityChange = (event, newValue) => { 582 | setVelocityValue(newValue); 583 | stateDebounceMyFunction("slider-tate", newValue); 584 | }; 585 | 586 | const [stateDebounceMyFunction] = useState(() => 587 | debounce(myFunction, 300, { 588 | leading: false, 589 | trailing: true 590 | }) 591 | ); 592 | 593 | useEffect(() => { 594 | if (context.current) { 595 | const { polydata, reduced, lookupTable, renderWindow, mapper } = context.current; 596 | reduced.nu(viscosityValue*1e-05); 597 | reduced.solveOnline(velocityValue, 0.0); 598 | reduced.reconstruct(); 599 | const newU = reduced.geometry(); 600 | polydata.getPointData().removeArray('uRec'); 601 | var nCells = polydata.getNumberOfPoints(); 602 | const array = vtkDataArray.newInstance({ 603 | name: 'uRec', 604 | size: nCells*3, 605 | numberOfComponents: 3, 606 | dataType: 'Float32Array' 607 | }); 608 | for (let i = 0; i < nCells; i++) { 609 | let v =[newU[i], newU[i + nCells], newU[i + nCells * 2]]; 610 | array.setTuple(i, v) 611 | } 612 | array.modified(); 613 | polydata.getPointData().setScalars(array) 614 | polydata.getPointData().addArray(array); 615 | polydata.getPointData().setActiveScalars("uRec"); 616 | const dataRange = [].concat(array ? array.getRange() : [0, 1]); 617 | lookupTable.setMappingRange(dataRange[0], dataRange[1]); 618 | lookupTable.updateRange(); 619 | mapper.setScalarRange(dataRange[0],dataRange[1]); 620 | mapper.update(); 621 | renderWindow.render(); 622 | } 623 | }, [viscosityValue, velocityValue]); 624 | 625 | const handleAdd = async newFiles => { 626 | setDisabled(true); 627 | newFiles = newFiles.filter(checkZip); 628 | newFiles = newFiles.filter(file => !files.find(f => f.data === file.data)); 629 | setFiles([...files, ...newFiles]); 630 | setDisabled(false); 631 | }; 632 | 633 | const handleDelete = deleted => { 634 | setFiles(files.filter(f => f !== deleted)); 635 | }; 636 | 637 | const handleFile = loadedFiles => { 638 | // console.log("loadedFiles: ", files) 639 | }; 640 | 641 | return ( 642 |
643 | { ! isConfirmed && 644 | 645 | 651 | 652 |
658 | Instructions 659 |
660 |
661 | - This tool handles data generated by ITHACA-FV SteadyNS and 662 | SteadyNSTurb classes (limited to 2D cases in this version). 663 |
664 |
665 | - Drag your ITHACAoutput folder in the area below, set ranges 666 | and confirm. 667 |
668 |
669 | - For a try-out: download and drag the following 670 | ZIP 671 | 674 | {' sample'} 675 | . 676 |
677 |
678 | - The files dragged and dropped will not be uploaded to any cloud or server, and 679 | will be processed locally in your device by the app. 680 |
681 |
682 | 683 |
684 | 692 | 696 | } 697 | dropzoneText={ 698 |
699 | Drag and drop here or click 700 |
701 | } 702 | previewText={ 703 |
704 | Preview files: 705 |
706 | } 707 | dropzoneParagraphClass={classes.dropzoneText} 708 | inputProps={{ classes: { root: classes.dropzone } }} 709 | previewChipProps={{ classes: { label: classes.dropzonePreview } }} 710 | filesLimit={1000} 711 | maxFileSize={30000000} 712 | showFileNamesInPreview={true} 713 | showFileNames={true} 714 | showPreviews={true} 715 | showPreviewsInDropzone={false} 716 | useChipsForPreview={true} 717 | showAlerts={false} 718 | fileObjects={files} 719 | onAdd={handleAdd} 720 | onDelete={handleDelete} 721 | onDrop={handleFile} 722 | /> 723 |
724 |
725 | 726 |
727 |
728 | Inlet velocity (m/s) 729 |
730 | 731 | 732 | {setUMin(event.target.value)}} 741 | /> 742 | {setUMax(event.target.value)}} 752 | /> 753 | 763 | } 764 | className={classes.bodyText} 765 | labelPlacement="end" 766 | label={
Fixed?
} 767 | /> 768 |
769 |
770 |
771 | 772 |
776 | Kinematic viscosity 777 |
778 |
779 | 780 | {setNuMin(event.target.value)}} 790 | /> 791 | {setNuMax(event.target.value)}} 802 | /> 803 | 813 | } 814 | className={classes.bodyText} 815 | labelPlacement="end" 816 | label={
Fixed?
} 817 | /> 818 |
819 |
820 | 828 | 834 |
835 |
836 |
837 |
838 |
839 |
840 | } 841 | { isConfirmed && 842 |
843 |
844 | {!dataLoaded && 845 |
853 |
859 | Loading and reading data... 860 |
861 |
866 | 867 |
868 |
869 | } 870 |
871 | {dataLoaded && 872 |
873 |
885 | 890 | 895 | 896 |
897 |
909 | 914 | 919 | 920 |
921 |
933 | 938 | 943 | 944 |
945 |
957 | 962 | 967 | 968 |
969 |
982 |
983 | { ! nuFixed && 984 |
985 | 986 | 995 | 996 |
} 997 | { ! nuFixed && 998 |
999 |
1000 | Kinematic viscosity (m2/s) x1e-05 1001 |
1002 |
1003 | } 1004 | { nuFixed && 1005 |
1006 | Kinematic viscosity (m2/s): {viscosityValue} 1007 |
1008 | } 1009 | { ! UFixed && 1010 |
1011 | 1012 | 1021 | 1022 |
1023 | } 1024 | { ! UFixed && 1025 |
1026 |
1027 | Inlet velocity (m/s) 1028 |
1029 |
} 1030 | { UFixed && 1031 |
1032 |
1033 | Inlet velocity (m/s): {velocityValue} 1034 |
1035 |
1036 | } 1037 |
1038 |
1039 |
1040 | } 1041 |
1042 | } 1043 |
1044 | ); 1045 | } 1046 | 1047 | export default Steady; 1048 | -------------------------------------------------------------------------------- /src/components/Tools/VTK/Slicer.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | import { lightTheme, darkTheme } from './../../theme'; 4 | import GenericView from './../../OF/GenericView'; 5 | 6 | import { makeStyles } from '@mui/styles'; 7 | import Box from '@mui/material/Box'; 8 | import Grid from '@mui/material/Grid' 9 | 10 | import { DropzoneAreaBase } from "react-mui-dropzone"; 11 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 12 | import { solid } from '@fortawesome/fontawesome-svg-core/import.macro' 13 | 14 | // - Tool custom data 15 | const vtuVariable = "U"; 16 | const vtuTitle = "Velocity magnitude (m/s)"; 17 | const codeLink = 'src/components/Tools/VTK/Slicer.jsx'; 18 | const repoRoot = 'https://github.com/simzero-oss/cfd-xyz-data/blob/main/' 19 | const simulationsLink = repoRoot + 'simulations_v1.1.0.gz?raw=true'; 20 | // 21 | 22 | function Slicer() { 23 | useEffect(() => { 24 | document.title = "/Tools/Slicer" 25 | }, []); 26 | 27 | const localTheme = window.localStorage.getItem('theme') || "light"; 28 | const theme = localTheme === 'light' ? lightTheme : darkTheme; 29 | const useStyles = makeStyles(theme); 30 | const classes = useStyles(); 31 | 32 | const [files, setFiles] = useState([]); 33 | const [isConfirmed,setConfirmed] = useState(false); 34 | 35 | const handleAdd = newFiles => { 36 | newFiles = newFiles.filter(checkFile); 37 | newFiles = newFiles.filter(file => !files.find(f => f.data === file.data)); 38 | setFiles([...files, ...newFiles]); 39 | }; 40 | 41 | const handleDelete = deleted => { 42 | setFiles(files.filter(f => f !== deleted)); 43 | }; 44 | 45 | const handleFile = loadedFiles => { 46 | // console.log("loadedFiles: ", files) 47 | }; 48 | 49 | const patterns = [ 50 | '.*.vtu' 51 | ]; 52 | 53 | function checkFile(item) { 54 | return item.file.name.match(patterns); 55 | } 56 | 57 | function clear() { 58 | setFiles([]); 59 | } 60 | 61 | const confirmed = async() => { 62 | setConfirmed(true); 63 | } 64 | 65 | return ( 66 |
67 | { ! isConfirmed && 68 | 69 | 75 | 76 |
82 | Instructions 83 |
84 |
85 | - This tool is a generic slicer for 3D unstructured grids. 86 |
87 |
88 | - Drag your .vtu file in the area below (or click and select) 89 | and confirm. 90 |
91 |
98 | - You can generate .vtu files in OpenFOAM running the following 99 | command in the terminal: 100 | 101 | {' foamToVTK -latestTime'} 102 | 103 | , and use in this tool the internal.vtu output in the VTK folder. 104 |
105 |
112 | - For a try-out: download, extract, and drag one of the 113 | internal.vtu files of this 114 | 117 | {' sample'} 118 | . 119 |
120 |
121 | - The files dragged and dropped will not be uploaded to any 122 | cloud or server, and will be processed locally in your device 123 | by the app. 124 |
125 |
126 | - CURRENT LIMITATIONS: velocity magnitude is the only variable 127 | displayed. 128 |
129 |
130 | 131 |
132 | 140 | 144 | } 145 | dropzoneText={ 146 |
147 | Drag and drop here or click 148 |
149 | } 150 | previewText={ 151 |
152 | Preview files: 153 |
154 | } 155 | dropzoneParagraphClass={classes.dropzoneText} 156 | inputProps={{ classes: { root: classes.dropzone } }} 157 | previewChipProps={{ classes: { label: classes.dropzonePreview } }} 158 | filesLimit={1000} 159 | maxFileSize={300000000} 160 | showFileNamesInPreview={true} 161 | showFileNames={true} 162 | showPreviews={true} 163 | showPreviewsInDropzone={false} 164 | useChipsForPreview={true} 165 | showAlerts={false} 166 | fileObjects={files} 167 | onAdd={handleAdd} 168 | onDelete={handleDelete} 169 | onDrop={handleFile} 170 | /> 171 |
172 |
173 | 174 |
175 |
176 | 184 | 190 |
191 |
192 |
193 |
194 |
195 | } 196 | { isConfirmed && 197 |
198 | 205 |
206 | } 207 |
208 | ); 209 | } 210 | 211 | export default Slicer; 212 | -------------------------------------------------------------------------------- /src/components/Tools/index.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | import { React, useEffect } from "react"; 6 | import Grid from '@mui/material/Grid' 7 | import ShowCards from './../Main/ShowCards'; 8 | import { makeStyles } from "@mui/styles"; 9 | import posts from "./list"; 10 | import { global } from './../theme'; 11 | 12 | function Tools() { 13 | useEffect(() => { 14 | document.title = "/Tools" 15 | }, []); 16 | 17 | const useStyles = makeStyles(global); 18 | const classes = useStyles(); 19 | 20 | return ( 21 |
22 | 27 | {posts.map(post => ( 28 | 29 | ))} 30 | 31 |
32 | ); 33 | } 34 | 35 | export default Tools; 36 | -------------------------------------------------------------------------------- /src/components/Tools/list.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | const posts = [ 6 | 7 | { 8 | title: "ITHACA-FV_Steady", 9 | link: "/Tools/ITHACA-FV_Steady", 10 | image: "/images/Tools/ITHACA-FV/ITHACA-FV", 11 | ready: true, 12 | key: "1", 13 | description: "..." 14 | }, 15 | 16 | { 17 | title: "3D Slicer", 18 | link: "/Tools/Slicer", 19 | image: "/images/Tools/VTK/VTK", 20 | ready: true, 21 | key: "2", 22 | description: "..." 23 | }, 24 | 25 | ] 26 | 27 | export default posts; 28 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | export { default as Navigation } from "./Main/Navigation"; 2 | export { default as Footer } from "./Main/Footer"; 3 | export { default as Home } from "./Main"; 4 | export { default as About } from "./Main/About"; 5 | export { default as Error } from "./Main/Error"; 6 | // OpenFOAM 7 | export { default as OF } from "./OF"; 8 | export { default as Incompressible } from "./OF/Incompressible"; 9 | export { default as SimpleFoam } from "./OF/Incompressible/SimpleFoam"; 10 | export { default as PitzDaily } from "./OF/Incompressible/SimpleFoam/PitzDaily"; 11 | export { default as Bump2D } from "./OF/Incompressible/SimpleFoam/Bump2D"; 12 | export { default as MixerVessel2D } from "./OF/Incompressible/SimpleFoam/MixerVessel2D"; 13 | export { default as MotorBike } from "./OF/Incompressible/SimpleFoam/MotorBike"; 14 | export { default as TurbineSiting } from "./OF/Incompressible/SimpleFoam/TurbineSiting"; 15 | export { default as WindAroundBuildings } from "./OF/Incompressible/SimpleFoam/WindAroundBuildings"; 16 | // Tools 17 | export { default as Tools } from "./Tools"; 18 | export { default as Steady } from "./Tools/ITHACA-FV/Steady"; 19 | export { default as Slicer } from "./Tools/VTK/Slicer"; 20 | // Other 21 | -------------------------------------------------------------------------------- /src/components/theme.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Carlos Peña-Monferrer. All rights reserved. 2 | // This work is licensed under the terms of the MIT license. 3 | // For a copy, see . 4 | 5 | const backgroundColor1 = '#f4f4f4' 6 | const backgroundColor2 = '#151515' 7 | const color1 = '#E2E2E2' 8 | const color2 = '#363537' 9 | const color1Alpha = 'rgba(226, 226, 226, 0.8)' 10 | const color2Alpha = 'rgba(54, 53, 55, 0.8)' 11 | 12 | const backgroundColorImage1 = '#5F9EA0' 13 | const backgroundColorImageDisabled1 = '#325354' 14 | const backgroundColorImage2 = '#708090' 15 | const backgroundColorImageDisabled2 = '#384048' 16 | 17 | const globalFont = 'Varela'; 18 | const cardBorder = 0; 19 | const cardWeight = '500'; 20 | const cardTitleWeight =' 500'; 21 | const toolsSize = 16; 22 | const vtkFontSize = 14; 23 | const cardDescriptionSize = 14; 24 | const bodySize = 14; 25 | const titleSize = 20; 26 | 27 | export const global = { 28 | root: { 29 | textAlignVertical: 'center', 30 | justifyContent: 'center', 31 | alignItems: 'center', 32 | paddingTop: 20, 33 | paddingBottom: 100, 34 | paddingRight: 20, 35 | paddingLeft: 20, 36 | }, 37 | fadeIn: { 38 | transition: 'opacity 2s ease' 39 | }, 40 | fadeOut: { 41 | transition: 'opacity 0s ease' 42 | } 43 | } 44 | 45 | export const lightTheme = { 46 | body: backgroundColor1, 47 | text: '#363537', 48 | toggleBorder: '#FFF', 49 | root: { 50 | textAlignVertical: 'center', 51 | justifyContent: 'center', 52 | alignItems: 'center', 53 | borderWidth: 0, 54 | backgroundColor: backgroundColor1, 55 | paddingTop: 15, 56 | paddingBottom: 100, 57 | paddingRight: 20, 58 | paddingLeft: 20, 59 | }, 60 | typography: { 61 | fontFamily: globalFont 62 | }, 63 | appBar: { 64 | height: 40, 65 | minHeight: 40, 66 | background: color1, 67 | }, 68 | bodyText: { 69 | color: backgroundColor2, 70 | fontFamily: globalFont, 71 | fontSize: bodySize, 72 | fontWeight: 500, 73 | letterSpacing: '0.5' 74 | }, 75 | titleText: { 76 | display: "flex", 77 | marginTop: 20, 78 | marginLeft: 0, 79 | marginRight: 0, 80 | marginBottom: 10, 81 | color: backgroundColor2, 82 | fontFamily: globalFont, 83 | fontSize: titleSize, 84 | fontWeight: 600, 85 | }, 86 | vtkText: { 87 | color: color2, 88 | fontWeight: cardWeight, 89 | fontFamily: globalFont, 90 | fontSize: vtkFontSize, 91 | borderColor: color2, 92 | }, 93 | controlLabel: { 94 | color: color2, 95 | fontFamily: globalFont, 96 | fontSize: vtkFontSize, 97 | }, 98 | dropzonePreview: { 99 | color: color2, 100 | fontFamily: globalFont, 101 | }, 102 | dropzoneActive: {}, 103 | dropzoneIcon: { 104 | paddingTop: 40, 105 | width: '100px', 106 | height: '100px', 107 | color: color2, 108 | }, 109 | dropzoneText: { 110 | paddingTop: 20, 111 | color: color2, 112 | fontFamily: globalFont, 113 | fontSize: bodySize, 114 | }, 115 | dropzone: { 116 | borderColor: color2, 117 | borderWidth: "1px", 118 | marginRight: 0, 119 | marginLeft: 0, 120 | marginBottom: 0, 121 | minWidth: '300px', 122 | width: '100%', 123 | background: backgroundColor1, 124 | fontFamily: globalFont, 125 | '&$dropzoneActive': { 126 | borderColor: 'blue', 127 | borderWidth: "3px", 128 | border: 'dashed', 129 | animation: 'linear infinite !important', 130 | backgroundImage: `repeating-linear-gradient(-45deg, ${color1}, ${color1} 25px, ${backgroundColor1} 25px, ${backgroundColor1} 50px)`, 131 | backgroundSize: '150% 100%', 132 | }, 133 | }, 134 | buttons: { 135 | color: color2, 136 | background: color1, 137 | width: '100px', 138 | height: '35px' 139 | }, 140 | viewButtonsPressed: { 141 | backgroundColor: color1Alpha, 142 | '&:hover': { 143 | cursor: 'pointer' 144 | } 145 | }, 146 | textField: { 147 | [`& fieldset`]: { 148 | borderRadius: 0 149 | }, 150 | "& .MuiFormLabel-root": { 151 | color: color2 152 | }, 153 | "& .MuiOutlinedInput-input": { 154 | "&::-webkit-outer-spin-button, &::-webkit-inner-spin-button": { 155 | "-webkit-appearance": "none", 156 | }, 157 | }, 158 | "& .MuiInputBase-input.Mui-disabled": { 159 | "-webkit-text-fill-color": 160 | color1, 161 | fontFamily: globalFont 162 | }, 163 | "& .MuiInputBase-input": { 164 | "-webkit-text-fill-color": 165 | color2, 166 | fontFamily: globalFont 167 | }, 168 | "& .MuiOutlinedInput-notchedOutline": { 169 | borderColor: color2 170 | }, 171 | "&:hover .MuiOutlinedInput-root .MuiOutlinedInput-notchedOutline": { 172 | borderColor: color2, 173 | borderWidth: "2px" 174 | }, 175 | "& .MuiInputLabel-outlined.Mui-focused": { 176 | color: color2, 177 | fontWeight: '600', 178 | }, 179 | "& .MuiOutlinedInput-root": { 180 | "&.Mui-focused fieldset": { 181 | borderColor: color2 182 | }, 183 | }, 184 | }, 185 | checked: { 186 | }, 187 | checkbox: { 188 | color: color2 189 | }, 190 | disabled: {}, 191 | mainWrapper: { 192 | background: backgroundColor1, 193 | position: 'relative', 194 | minHeight: '100vh' 195 | }, 196 | slider: { 197 | '& .MuiSlider-thumb': { 198 | color: color2, 199 | '&:focus, &:hover, &.Mui-active, &.Mui-focusVisible': { 200 | boxShadow: 'inherit', 201 | }, 202 | '&:before': { 203 | display: 'none', 204 | }, 205 | }, 206 | '& .MuiSlider-track': { 207 | color: color2, 208 | border: 'none' 209 | }, 210 | '& .MuiSlider-rail': { 211 | color: backgroundColor2 212 | } 213 | }, 214 | footer: { 215 | position: 'relative', 216 | //marginTop: '-180px', 217 | //height: '180px', 218 | clear: 'both', 219 | paddingTop: 20, 220 | paddingBottom: 20, 221 | }, 222 | cardTextTools: { 223 | backgroundColor: backgroundColorImage1, 224 | borderWidth: '2px', 225 | borderStyle: 'solid', 226 | borderColor: color2, 227 | fontWeight: cardWeight, 228 | fontFamily: globalFont, 229 | fontSize: toolsSize, 230 | maxWidth: '250px', 231 | minHeight: '50px', 232 | alignItems: 'center', 233 | display: 'flex', 234 | paddingLeft: 10, 235 | flexDrection: 'column', 236 | }, 237 | cardTitle: { 238 | fontSize: 14, 239 | fontFamily: globalFont, 240 | maxHeight: 25, 241 | paddingRight: 10, 242 | paddingTop: 5, 243 | fontWeight: cardTitleWeight, 244 | flexDrection: 'column', 245 | textAlign: 'center', 246 | justifyContent: "right", 247 | textAlignVertical: "center", 248 | display: 'flex', 249 | alignItems: 'center' 250 | }, 251 | cardDescription: { 252 | color: color2, 253 | paddingTop: 40, 254 | paddingRight: 20, 255 | paddingLeft: 20, 256 | float: 'left', 257 | textAlign: 'left', 258 | whiteSpace: 'pre-line', 259 | backgroundColor: backgroundColorImage1, 260 | fontWeight: 400, 261 | fontSize: cardDescriptionSize, 262 | fontFamily: globalFont, 263 | }, 264 | cardDescriptionMobile: { 265 | color: color2, 266 | paddingTop: 15, 267 | paddingRight: 20, 268 | paddingLeft: 20, 269 | float: 'left', 270 | textAlign: 'left', 271 | whiteSpace: 'pre-line', 272 | backgroundColor: backgroundColorImage1, 273 | fontWeight: 400, 274 | fontSize: cardDescriptionSize-2, 275 | fontFamily: globalFont, 276 | }, 277 | palette: { 278 | primary1Color: color1, 279 | primary2Color: color2 280 | }, 281 | cardMedia: { 282 | maxWidth: 1200, 283 | width: '100%' 284 | }, 285 | cardIcon: { 286 | opacity: '0.8', 287 | fontSize: "20px", 288 | color: color2 289 | }, 290 | cardMain: { 291 | background: 'green' 292 | }, 293 | cardActive: { 294 | boxShadow: 'none', 295 | background: backgroundColorImage1, 296 | color: color1, 297 | borderWidth: cardBorder, 298 | borderStyle: 'solid', 299 | borderColor: 'black', 300 | borderRadius: 0, 301 | paddingLeft: 0, 302 | paddingRight:0, 303 | paddingTop:0, 304 | paddingBottom: 0, 305 | maxWidth: 1200 306 | }, 307 | cardDisabled: { 308 | boxShadow: 'none', 309 | background: backgroundColorImageDisabled1, 310 | color: color1, 311 | borderWidth: cardBorder, 312 | borderStyle: 'solid', 313 | borderColor: 'black', 314 | borderRadius: 0, 315 | paddingLeft: 0, 316 | paddingRight:0, 317 | paddingTop:0, 318 | paddingBottom: 0, 319 | maxWidth: 1200 320 | }, 321 | tooltip: { 322 | "& .MuiTooltip-tooltip": { 323 | padding: 8, 324 | backgroundColor: color1, 325 | background: backgroundColor1, 326 | boxShadow: "1px 2px 1px #9E9E9E", 327 | maxWidth: 150, 328 | }, 329 | "& .MuiTooltip-arrow": { 330 | color: color1 331 | } 332 | }, 333 | link: { 334 | fontFamily: globalFont, 335 | fontWeight: cardTitleWeight, 336 | color: color2, 337 | textDecoration: 'none!important', 338 | '&:hover': { 339 | color: backgroundColor2, 340 | textDecoration: 'none', 341 | fontFamily: globalFont 342 | } 343 | } 344 | } 345 | 346 | export const darkTheme = { 347 | body: backgroundColor2, 348 | text: '#FAFAFA', 349 | toggleBorder: '#6B8096', 350 | root: { 351 | textAlignVertical: 'center', 352 | justifyContent: 'center', 353 | alignItems: 'center', 354 | //minHeight: '100vh', 355 | borderWidth: 0, 356 | backgroundColor: backgroundColor2, 357 | paddingTop: 15, 358 | paddingBottom: 100, 359 | paddingRight: 20, 360 | paddingLeft: 20, 361 | //maxHeight: '10px' 362 | }, 363 | typography: { 364 | fontFamily: globalFont 365 | }, 366 | appBar: { 367 | height: 40, 368 | minHeight: 40, 369 | background: color2, 370 | }, 371 | bodyText: { 372 | color: color1, 373 | fontFamily: globalFont, 374 | fontSize: bodySize, 375 | fontWeight: 500, 376 | letterSpacing: '0.5' 377 | }, 378 | titleText: { 379 | display: "flex", 380 | marginTop: 20, 381 | marginLeft: 0, 382 | marginRight: 0, 383 | marginBottom: 10, 384 | color: color1, 385 | fontFamily: globalFont, 386 | fontSize: titleSize, 387 | fontWeight: 600, 388 | }, 389 | vtkText: { 390 | color: color1, 391 | fontWeight: cardWeight, 392 | fontFamily: globalFont, 393 | fontSize: vtkFontSize, 394 | }, 395 | controlLabel: { 396 | color: color1, 397 | fontFamily: globalFont, 398 | fontSize: vtkFontSize, 399 | }, 400 | dropzonePreview: { 401 | color: color1, 402 | fontFamily: globalFont, 403 | }, 404 | dropzoneActive: {}, 405 | dropzoneIcon: { 406 | paddingTop: 40, 407 | width: '100px', 408 | height: '100px', 409 | color: color1, 410 | }, 411 | dropzoneText: { 412 | paddingTop: 20, 413 | color: color1, 414 | fontFamily: globalFont, 415 | fontSize: bodySize, 416 | }, 417 | dropzone: { 418 | borderColor: backgroundColor1, 419 | borderWidth: "1px", 420 | marginRight: 0, 421 | marginLeft: 0, 422 | marginBottom: 0, 423 | minWidth: '300px', 424 | width: '100%', 425 | background: backgroundColor2, 426 | fontFamily: globalFont, 427 | '&$dropzoneActive': { 428 | borderColor: 'blue', 429 | borderWidth: "3px", 430 | border: 'dashed', 431 | animation: 'linear infinite !important', 432 | backgroundImage: `repeating-linear-gradient(-45deg, ${color2}, ${color2} 25px, ${backgroundColor2} 25px, ${backgroundColor2} 50px)`, 433 | backgroundSize: '150% 100%', 434 | }, 435 | }, 436 | buttons: { 437 | color: color1, 438 | background: color2, 439 | width: '100px', 440 | height: '35px' 441 | }, 442 | viewButtonsPressed: { 443 | backgroundColor: color2Alpha, 444 | '&:hover': { 445 | cursor: 'pointer' 446 | } 447 | }, 448 | textField: { 449 | [`& fieldset`]: { 450 | borderRadius: 0 451 | }, 452 | "& .MuiFormLabel-root": { 453 | color: color1 454 | }, 455 | "& .MuiFormLabel-root.Mui-disabled": { 456 | color: color2 457 | }, 458 | "& .MuiOutlinedInput-input": { 459 | "&::-webkit-outer-spin-button, &::-webkit-inner-spin-button": { 460 | "-webkit-appearance": "none", 461 | }, 462 | }, 463 | "& .MuiInputBase-input.Mui-disabled": { 464 | "-webkit-text-fill-color": color2, 465 | fontFamily: globalFont 466 | }, 467 | "& .MuiOutlinedInput-root .Mui-disabled .MuiOutlinedInput-notchedOutline": { 468 | color: 'purple', 469 | borderWidth: "2px" 470 | }, 471 | "& .MuiInputBase-input": { 472 | "-webkit-text-fill-color": 473 | color1, 474 | fontFamily: globalFont 475 | }, 476 | "& .MuiOutlinedInput-notchedOutline": { 477 | borderColor: color1 478 | }, 479 | "& .MuiOutlinedInput-root .MuiOutlinedInput-notchedOutline .Mui-disabled": { 480 | borderColor: 'purple', 481 | borderWidth: "2px", 482 | color: 'purple' 483 | }, 484 | "&:hover .MuiOutlinedInput-root .MuiOutlinedInput-notchedOutline": { 485 | borderColor: color1, 486 | borderWidth: "2px" 487 | }, 488 | "& .MuiOutlinedInput-root.Mui-disabled fieldset": { 489 | borderColor: color2 490 | }, 491 | "& .MuiInputLabel-outlined.Mui-focused": { 492 | color: color1, 493 | fontWeight: '600', 494 | }, 495 | }, 496 | checked: { 497 | }, 498 | checkbox: { 499 | color: color1 500 | }, 501 | disabled: {}, 502 | mainWrapper: { 503 | background: backgroundColor2, 504 | position: 'relative', 505 | minHeight: '100vh' 506 | }, 507 | slider: { 508 | '& .MuiSlider-valueLabel': { 509 | fontFamily: globalFont, 510 | fontSize: 12, 511 | }, 512 | '& .MuiSlider-thumb': { 513 | color: color1 514 | }, 515 | '& .MuiSlider-track': { 516 | color: color1 517 | }, 518 | '& .MuiSlider-rail': { 519 | color: backgroundColor1 520 | } 521 | }, 522 | footer: { 523 | position: 'relative', 524 | //marginTop: '-180px', 525 | //height: '180px', 526 | clear: 'both', 527 | paddingTop: 20, 528 | paddingBottom: 20, 529 | }, 530 | cardTextTools: { 531 | backgroundColor: backgroundColorImage2, 532 | borderWidth: '2px', 533 | borderStyle: 'solid', 534 | borderColor: color2, 535 | fontWeight: cardWeight, 536 | fontFamily: globalFont, 537 | fontSize: toolsSize, 538 | maxWidth: '250px', 539 | minHeight: '50px', 540 | alignItems: 'center', 541 | display: 'flex', 542 | paddingLeft: 10, 543 | flexDrection: 'column', 544 | }, 545 | cardTitle: { 546 | fontSize: 14, 547 | fontFamily: globalFont, 548 | maxHeight: 25, 549 | paddingRight: 10, 550 | paddingTop: 5, 551 | fontWeight: cardTitleWeight, 552 | flexDrection: 'column', 553 | textAlign: 'center', 554 | justifyContent: "right", 555 | textAlignVertical: "center", 556 | display: 'flex', 557 | alignItems: 'center' 558 | }, 559 | cardDescription: { 560 | color: color1, 561 | paddingTop: 40, 562 | paddingRight: 20, 563 | paddingLeft: 20, 564 | float: 'left', 565 | textAlign: 'left', 566 | whiteSpace: 'pre-line', 567 | backgroundColor: backgroundColorImage2, 568 | fontWeight: 400, 569 | fontSize: cardDescriptionSize, 570 | fontFamily: globalFont 571 | }, 572 | cardDescriptionMobile: { 573 | color: color1, 574 | paddingTop: 15, 575 | paddingRight: 20, 576 | paddingLeft: 20, 577 | float: 'left', 578 | textAlign: 'left', 579 | whiteSpace: 'pre-line', 580 | backgroundColor: backgroundColorImage2, 581 | fontWeight: 400, 582 | fontSize: cardDescriptionSize-2, 583 | fontFamily: globalFont, 584 | }, 585 | palette: { 586 | primary1Color: color2, 587 | primary2Color: color1 588 | }, 589 | cardMedia: { 590 | maxWidth: 1200, 591 | width: '100%' 592 | }, 593 | cardIcon: { 594 | opacity: '0.8', 595 | fontSize: "20px", 596 | color: color2 597 | }, 598 | cardMain: { 599 | background: backgroundColorImage2 600 | }, 601 | cardActive: { 602 | boxShadow: 'none', 603 | background: backgroundColorImage2, 604 | color: color1, 605 | borderWidth: cardBorder, 606 | borderStyle: 'solid', 607 | borderColor: 'black', 608 | borderRadius: 0, 609 | paddingLeft: 0, 610 | paddingRight:0, 611 | paddingTop:0, 612 | paddingBottom: 0, 613 | maxWidth: 1200, 614 | }, 615 | cardDisabled: { 616 | boxShadow: 'none', 617 | background: backgroundColorImageDisabled2, 618 | color: color1, 619 | borderWidth: cardBorder, 620 | borderStyle: 'solid', 621 | borderColor: 'black', 622 | borderRadius: 0, 623 | paddingLeft: 0, 624 | paddingRight:0, 625 | paddingTop:0, 626 | paddingBottom: 0, 627 | maxWidth: 1200, 628 | }, 629 | tooltip: { 630 | "& .MuiTooltip-tooltip": { 631 | padding: 8, 632 | backgroundColor: color2, 633 | background: backgroundColor2, 634 | maxWidth: 150, 635 | }, 636 | "& .MuiTooltip-arrow": { 637 | color: color2 638 | } 639 | }, 640 | link: { 641 | fontFamily: globalFont, 642 | fontWeight: cardTitleWeight, 643 | color: color1, 644 | textDecoration: 'none!important', 645 | '&:hover': { 646 | color: backgroundColor1, 647 | textDecoration: 'none', 648 | fontFamily: globalFont 649 | } 650 | } 651 | } 652 | 653 | export const navTheme = { 654 | links: { 655 | color: color2, 656 | textDecoration: 'none!important', 657 | fontFamily: globalFont, 658 | fontSize: 15, 659 | fontWeight: 500, 660 | letterSpacing: '0.5', 661 | '&:hover': { 662 | color: color2, 663 | fontFamily: globalFont 664 | } 665 | }, 666 | root: { 667 | display: "flex", 668 | margin: "0px", 669 | }, 670 | logo: { 671 | maxWidth: 110, 672 | paddingLeft: 0, 673 | paddingRight:0, 674 | paddingTop:0, 675 | paddingBottom: 0 676 | } 677 | } 678 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import "@fontsource/varela"; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | --------------------------------------------------------------------------------