├── LICENSE ├── Pipfile ├── Pipfile.lock ├── PythonReader1.exe ├── README.md ├── abaqusODBProcess.py ├── abaqusPythonScript.py ├── dispForce.gif ├── launcher.bat ├── main_Run.py ├── misesStress.gif ├── postResults ├── PEEQ.txt ├── dispX.txt ├── dispY.txt ├── dispZ.txt ├── elements.txt ├── misesStress.txt ├── nodes.txt ├── refDisp.txt └── refLoad.txt ├── prePostProcess.py ├── prePostProcess.py.bak ├── requirements.txt ├── runAbaqus.py └── saveDataToSqlite.py /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.tuna.tsinghua.edu.cn/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | 8 | [packages] 9 | pyvista = "==0.25.3" 10 | records = "==0.5.3" 11 | numpy = "==1.19.1" 12 | 13 | [requires] 14 | python_version = "3.6" 15 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "196465fa120306f94539a269bf3c9e1e46533d108947ea6a4b1c02e5b8403923" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.6" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.tuna.tsinghua.edu.cn/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "appdirs": { 20 | "hashes": [ 21 | "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", 22 | "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" 23 | ], 24 | "version": "==1.4.4" 25 | }, 26 | "docopt": { 27 | "hashes": [ 28 | "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" 29 | ], 30 | "version": "==0.6.2" 31 | }, 32 | "et-xmlfile": { 33 | "hashes": [ 34 | "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b" 35 | ], 36 | "version": "==1.0.1" 37 | }, 38 | "imageio": { 39 | "hashes": [ 40 | "sha256:3604d751f03002e8e0e7650aa71d8d9148144a87daf17cb1f3228e80747f2e6b", 41 | "sha256:52ddbaeca2dccf53ba2d6dec5676ca7bc3b2403ef8b37f7da78b7654bb3e10f0" 42 | ], 43 | "version": "==2.9.0" 44 | }, 45 | "importlib-metadata": { 46 | "hashes": [ 47 | "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83", 48 | "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070" 49 | ], 50 | "markers": "python_version < '3.8'", 51 | "version": "==1.7.0" 52 | }, 53 | "jdcal": { 54 | "hashes": [ 55 | "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba", 56 | "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8" 57 | ], 58 | "version": "==1.4.1" 59 | }, 60 | "meshio": { 61 | "hashes": [ 62 | "sha256:33ad81bc91f33983dd58f727b27fa117a7ce49623e11f10a2348204daa317f1e", 63 | "sha256:fed50ad79effc167c36a7ac6a90ce0bf284c3484136414642b803e78080cacac" 64 | ], 65 | "markers": "python_version >= '3.5'", 66 | "version": "==4.1.1" 67 | }, 68 | "numpy": { 69 | "hashes": [ 70 | "sha256:082f8d4dd69b6b688f64f509b91d482362124986d98dc7dc5f5e9f9b9c3bb983", 71 | "sha256:1bc0145999e8cb8aed9d4e65dd8b139adf1919e521177f198529687dbf613065", 72 | "sha256:309cbcfaa103fc9a33ec16d2d62569d541b79f828c382556ff072442226d1968", 73 | "sha256:3673c8b2b29077f1b7b3a848794f8e11f401ba0b71c49fbd26fb40b71788b132", 74 | "sha256:480fdd4dbda4dd6b638d3863da3be82873bba6d32d1fc12ea1b8486ac7b8d129", 75 | "sha256:56ef7f56470c24bb67fb43dae442e946a6ce172f97c69f8d067ff8550cf782ff", 76 | "sha256:5a936fd51049541d86ccdeef2833cc89a18e4d3808fe58a8abeb802665c5af93", 77 | "sha256:5b6885c12784a27e957294b60f97e8b5b4174c7504665333c5e94fbf41ae5d6a", 78 | "sha256:667c07063940e934287993366ad5f56766bc009017b4a0fe91dbd07960d0aba7", 79 | "sha256:7ed448ff4eaffeb01094959b19cbaf998ecdee9ef9932381420d514e446601cd", 80 | "sha256:8343bf67c72e09cfabfab55ad4a43ce3f6bf6e6ced7acf70f45ded9ebb425055", 81 | "sha256:92feb989b47f83ebef246adabc7ff3b9a59ac30601c3f6819f8913458610bdcc", 82 | "sha256:935c27ae2760c21cd7354402546f6be21d3d0c806fffe967f745d5f2de5005a7", 83 | "sha256:aaf42a04b472d12515debc621c31cf16c215e332242e7a9f56403d814c744624", 84 | "sha256:b12e639378c741add21fbffd16ba5ad25c0a1a17cf2b6fe4288feeb65144f35b", 85 | "sha256:b1cca51512299841bf69add3b75361779962f9cee7d9ee3bb446d5982e925b69", 86 | "sha256:b8456987b637232602ceb4d663cb34106f7eb780e247d51a260b84760fd8f491", 87 | "sha256:b9792b0ac0130b277536ab8944e7b754c69560dac0415dd4b2dbd16b902c8954", 88 | "sha256:c9591886fc9cbe5532d5df85cb8e0cc3b44ba8ce4367bd4cf1b93dc19713da72", 89 | "sha256:cf1347450c0b7644ea142712619533553f02ef23f92f781312f6a3553d031fc7", 90 | "sha256:de8b4a9b56255797cbddb93281ed92acbc510fb7b15df3f01bd28f46ebc4edae", 91 | "sha256:e1b1dc0372f530f26a03578ac75d5e51b3868b9b76cd2facba4c9ee0eb252ab1", 92 | "sha256:e45f8e981a0ab47103181773cc0a54e650b2aef8c7b6cd07405d0fa8d869444a", 93 | "sha256:e4f6d3c53911a9d103d8ec9518190e52a8b945bab021745af4939cfc7c0d4a9e", 94 | "sha256:ed8a311493cf5480a2ebc597d1e177231984c818a86875126cfd004241a73c3e", 95 | "sha256:ef71a1d4fd4858596ae80ad1ec76404ad29701f8ca7cdcebc50300178db14dfc" 96 | ], 97 | "index": "pypi", 98 | "version": "==1.19.1" 99 | }, 100 | "openpyxl": { 101 | "hashes": [ 102 | "sha256:626d38647c063d55803ef4971c4d43226538d4e95cb6260c094e363ee33e10c7" 103 | ], 104 | "version": "==2.4.11" 105 | }, 106 | "pillow": { 107 | "hashes": [ 108 | "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f", 109 | "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8", 110 | "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad", 111 | "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f", 112 | "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae", 113 | "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d", 114 | "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5", 115 | "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b", 116 | "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8", 117 | "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233", 118 | "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6", 119 | "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727", 120 | "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f", 121 | "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38", 122 | "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4", 123 | "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626", 124 | "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d", 125 | "sha256:9c87ef410a58dd54b92424ffd7e28fd2ec65d2f7fc02b76f5e9b2067e355ebf6", 126 | "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6", 127 | "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63", 128 | "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f", 129 | "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41", 130 | "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1", 131 | "sha256:e901964262a56d9ea3c2693df68bc9860b8bdda2b04768821e4c44ae797de117", 132 | "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d", 133 | "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9", 134 | "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a", 135 | "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce" 136 | ], 137 | "markers": "python_version >= '3.5'", 138 | "version": "==7.2.0" 139 | }, 140 | "pyvista": { 141 | "hashes": [ 142 | "sha256:02e916ca94413b8c88c1cd83b37d6ec860bd91f07c70436777208954541d3889", 143 | "sha256:576479045bdee6843f5f50eb4c9844efbf5cd82022c789ce564956a2ea948428" 144 | ], 145 | "index": "pypi", 146 | "version": "==0.25.3" 147 | }, 148 | "records": { 149 | "hashes": [ 150 | "sha256:47e4874096f4a8f4b5bcad8c7c7cf512be36186e6e263ff3dfd750b05ff0d3c4", 151 | "sha256:cdbacf52c61b4a3bc10fef1286a24a63ae95255a2e7b4e8ccb1e1f96737231ed" 152 | ], 153 | "index": "pypi", 154 | "version": "==0.5.3" 155 | }, 156 | "scooby": { 157 | "hashes": [ 158 | "sha256:5a194438edb02b18dd49be1e37570735486386413bb9ea0749dbf218a68104ea", 159 | "sha256:eb9f11d2aa281fc672c68e62ac3e7d66db48a07004bdea595e74862c2d361bb3" 160 | ], 161 | "version": "==0.5.6" 162 | }, 163 | "sqlalchemy": { 164 | "hashes": [ 165 | "sha256:072766c3bd09294d716b2d114d46ffc5ccf8ea0b714a4e1c48253014b771c6bb", 166 | "sha256:107d4af989831d7b091e382d192955679ec07a9209996bf8090f1f539ffc5804", 167 | "sha256:15c0bcd3c14f4086701c33a9e87e2c7ceb3bcb4a246cd88ec54a49cf2a5bd1a6", 168 | "sha256:26c5ca9d09f0e21b8671a32f7d83caad5be1f6ff45eef5ec2f6fd0db85fc5dc0", 169 | "sha256:276936d41111a501cf4a1a0543e25449108d87e9f8c94714f7660eaea89ae5fe", 170 | "sha256:3292a28344922415f939ee7f4fc0c186f3d5a0bf02192ceabd4f1129d71b08de", 171 | "sha256:33d29ae8f1dc7c75b191bb6833f55a19c932514b9b5ce8c3ab9bc3047da5db36", 172 | "sha256:3bba2e9fbedb0511769780fe1d63007081008c5c2d7d715e91858c94dbaa260e", 173 | "sha256:465c999ef30b1c7525f81330184121521418a67189053bcf585824d833c05b66", 174 | "sha256:51064ee7938526bab92acd049d41a1dc797422256086b39c08bafeffb9d304c6", 175 | "sha256:5a49e8473b1ab1228302ed27365ea0fadd4bf44bc0f9e73fe38e10fdd3d6b4fc", 176 | "sha256:618db68745682f64cedc96ca93707805d1f3a031747b5a0d8e150cfd5055ae4d", 177 | "sha256:6547b27698b5b3bbfc5210233bd9523de849b2bb8a0329cd754c9308fc8a05ce", 178 | "sha256:6557af9e0d23f46b8cd56f8af08eaac72d2e3c632ac8d5cf4e20215a8dca7cea", 179 | "sha256:73a40d4fcd35fdedce07b5885905753d5d4edf413fbe53544dd871f27d48bd4f", 180 | "sha256:8280f9dae4adb5889ce0bb3ec6a541bf05434db5f9ab7673078c00713d148365", 181 | "sha256:83469ad15262402b0e0974e612546bc0b05f379b5aa9072ebf66d0f8fef16bea", 182 | "sha256:860d0fe234922fd5552b7f807fbb039e3e7ca58c18c8d38aa0d0a95ddf4f6c23", 183 | "sha256:883c9fb62cebd1e7126dd683222b3b919657590c3e2db33bdc50ebbad53e0338", 184 | "sha256:8afcb6f4064d234a43fea108859942d9795c4060ed0fbd9082b0f280181a15c1", 185 | "sha256:96f51489ac187f4bab588cf51f9ff2d40b6d170ac9a4270ffaed535c8404256b", 186 | "sha256:9e865835e36dfbb1873b65e722ea627c096c11b05f796831e3a9b542926e979e", 187 | "sha256:aa0554495fe06172b550098909be8db79b5accdf6ffb59611900bea345df5eba", 188 | "sha256:b595e71c51657f9ee3235db8b53d0b57c09eee74dfb5b77edff0e46d2218dc02", 189 | "sha256:b6ff91356354b7ff3bd208adcf875056d3d886ed7cef90c571aef2ab8a554b12", 190 | "sha256:b70bad2f1a5bd3460746c3fb3ab69e4e0eb5f59d977a23f9b66e5bdc74d97b86", 191 | "sha256:c7adb1f69a80573698c2def5ead584138ca00fff4ad9785a4b0b2bf927ba308d", 192 | "sha256:c898b3ebcc9eae7b36bd0b4bbbafce2d8076680f6868bcbacee2d39a7a9726a7", 193 | "sha256:e49947d583fe4d29af528677e4f0aa21f5e535ca2ae69c48270ebebd0d8843c0", 194 | "sha256:eb1d71643e4154398b02e88a42fc8b29db8c44ce4134cf0f4474bfc5cb5d4dac", 195 | "sha256:f2e8a9c0c8813a468aa659a01af6592f71cd30237ec27c4cc0683f089f90dcfc", 196 | "sha256:fe7fe11019fc3e6600819775a7d55abc5446dda07e9795f5954fdbf8a49e1c37" 197 | ], 198 | "markers": "python_version >= '3.0'", 199 | "version": "==1.3.19" 200 | }, 201 | "tablib": { 202 | "hashes": [ 203 | "sha256:8cc2fa10bc37219ac5e76850eb7fbd50de313c7a1a7895c44af2a8dd206b7be7", 204 | "sha256:c5a77c96ad306d5b380def1309d521ad5e98b4f83726f84857ad87e142d13279" 205 | ], 206 | "markers": "python_version >= '3.5'", 207 | "version": "==2.0.0" 208 | }, 209 | "vtk": { 210 | "hashes": [ 211 | "sha256:11c7b05e2a35ff5724b5c88a90ffaa1de84347ddc8293c1b74158c721db31573", 212 | "sha256:3b0873e79365268b3b7d2acb238d2333f73209c27f54b76dc0cdd85483afa82e", 213 | "sha256:4092bf85e1d02a76ea878bb9b822eb57ec7b73c8826e3ec29f1c8cbddcb312e3", 214 | "sha256:424d7e6f8a216b7af82c672ebae82bc6e268582f802c7b32684ae9a90ef4c19e", 215 | "sha256:b9d3827bf84ca11a669cf798d2a205d4ca19ed66e15e93ab2ab747f9dbe9edbe", 216 | "sha256:bd4a066dbb4fb35d329278538976ad4440aeb0e5c839cc12310567238211971c", 217 | "sha256:bd6efb3d3a6ead36e42ab938806364fa7dc858228a1c81e321556e43ff899d89", 218 | "sha256:cbf17bc5ab7ccbda79458cf241cad8bc790a228dfa15066c50648bfb5d7abeb1", 219 | "sha256:cdc7d6d556cf520e6c3c76299125a71d7be5895744ba949e2560d9332e607b50", 220 | "sha256:e2ce620b2691ee8770bd9bfc0ae2ca99c0263ded20559c389a10b9b78e7750b2", 221 | "sha256:e6bfc40f4cdc02f8b869b0c2023b73c6aad86fdb39fcb1823b1f4f5efd1a0001" 222 | ], 223 | "version": "==9.0.1" 224 | }, 225 | "zipp": { 226 | "hashes": [ 227 | "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", 228 | "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" 229 | ], 230 | "markers": "python_version >= '3.6'", 231 | "version": "==3.1.0" 232 | } 233 | }, 234 | "develop": {} 235 | } 236 | -------------------------------------------------------------------------------- /PythonReader1.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Junjun1guo/pythonInteractAbaqus/364cf248b161bbd9760540cc86d4bd06d4eff667/PythonReader1.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | Author: Junjun Guo([HomePage](https://github.com/Junjun1guo)) 3 | E-mail: guojj@tongji.edu.cn/guojj_ce@163.com 4 | Environemet: Successfully excucted in python 3.8 5 | ########################################################################## 6 | ______ 7 | A general pre and post process framework for finite element analysis, such as ABAQUS, OpenSees et al. 8 | 9 | 10 | 11 | ## Usage 12 | 1. __Generate finite element model__. If use commercial software,such as ABAQUS, you can write python script to establish FEM(referring __abaqusPythonScript.py__). If use open source software, such as OpenSees, you can also write python script to generate the input file(referring __abaqusPythonScript.py__). In additon, for two or three dimensional problems, [pygmsh](https://github.com/nschloe/pygmsh) can be used to mesh the model. 13 | 2. __outPut process__. If use commercial software,such as ABAQUS, you can write python script to read the output database(referring __abaqusODBProcess.py__).If use open source software, such as OpenSees, you can process the output files and save data to [pysqlite](https://github.com/ghaering/pysqlite) database(referring __saveDataToSqlite.py__). 14 | 3. __result display__. [pyvista](https://docs.pyvista.org/) is adopted to generate static and dynamic graphs(referring __prePostProcess.py__). 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /abaqusODBProcess.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @File : 234.py 3 | # @Date : 2020-09-02 18:14 4 | # @Email : {guojj@tongji.edu.cn/guojj01@gmail.com} 5 | # @Author : guojj 6 | 7 | 8 | ###导入必要的模块 9 | from odbAccess import * 10 | from abaqusConstants import * 11 | from odbMaterial import * 12 | from odbSection import * 13 | import numpy as np 14 | import os 15 | 16 | 17 | 18 | class abaqusODBProcess(object): 19 | """基于python的Abaqus前后处理程序.""" 20 | 21 | def __init__(self,odbPath): 22 | self._odb = openOdb(path=odbPath) #打开结果数据库 23 | 24 | @property 25 | def steps(self): 26 | """返回模型荷载步,编号规则stepName_number,number 从1到N""" 27 | totalSteps=self._odb.steps.keys() 28 | stepName=totalSteps[0].split('_')[0] 29 | numStep=len(totalSteps) 30 | return stepName,numStep 31 | 32 | @property 33 | def instance(self): 34 | """返回装配件实例""" 35 | print(self._odb.rootAssembly.instances.keys()) 36 | 37 | return self._odb.rootAssembly.instances.keys()[1] 38 | 39 | @property 40 | def nodes(self): 41 | """返回模型节点列表,[[number1,x1,y1,z1],...]""" 42 | nodes = self._odb.rootAssembly.instances[self.instance].nodes 43 | nodeList=[[each.label]+list(each.coordinates) for each in nodes] 44 | return nodeList 45 | 46 | @property 47 | def elements(self): 48 | """返回模型单元列表,[[eleNum1,node1i,node1j,...],...]""" 49 | elements = self._odb.rootAssembly.instances[self.instance].elements 50 | eleList=[[each.label]+list(each.connectivity) for each in elements] 51 | return eleList 52 | 53 | def rfNodeResponse(self,nodedSetName,component): 54 | """ 55 | 返回参考点响应列表[[rx0,ry0,rz0],...] 56 | :param nodedSetName: 节点集名称 57 | :param component:分量名称,如‘U’,‘RF’等 58 | """ 59 | endSet=self._odb.rootAssembly.nodeSets[nodedSetName] 60 | returnList = [] 61 | stepName,numSteps=self.steps 62 | print(numSteps) 63 | for i1 in range(numSteps): 64 | flag = True 65 | j1 = 0 66 | while (flag): 67 | try: 68 | frame = self._odb.steps[stepName+"_" + str(i1 + 1)].frames[j1] 69 | j1 = j1 + 1 70 | displacement = frame.fieldOutputs[component] 71 | centerDisplacement = displacement.getSubset(region=endSet) 72 | fieldValues = centerDisplacement.values 73 | for v in fieldValues: 74 | returnList.append(v.data) 75 | except: 76 | flag = False 77 | return returnList 78 | 79 | def nodeDisp(self): 80 | """返回节点位移,dispXList,dispYList,dispZList""" 81 | stepName, numSteps = self.steps 82 | returnDict = {} 83 | for i1 in range(numSteps): 84 | flag = True 85 | j1 = 0 86 | while (flag): 87 | try: 88 | frame = self._odb.steps[stepName +"_"+ str(i1 + 1)].frames[j1] 89 | j1 = j1 + 1 90 | displacement = frame.fieldOutputs['U'].values 91 | for each in displacement: 92 | if not returnDict.has_key(each.nodeLabel): 93 | returnDict[each.nodeLabel] = [] 94 | returnDict[each.nodeLabel].append(each.data) 95 | else: 96 | returnDict[each.nodeLabel].append(each.data) 97 | except: 98 | flag = False 99 | changeValue = [returnDict[1][i1 * 2] for i1 in range(len(returnDict[1]) / 2)] 100 | returnDict[1] = changeValue 101 | dispXList=[] 102 | dispYList=[] 103 | dispZList=[] 104 | for i1 in range(len(returnDict)): 105 | tempValueX=[each[0] for each in returnDict[i1+1]] 106 | tempValueY = [each[1] for each in returnDict[i1 + 1]] 107 | tempValueZ = [each[2] for each in returnDict[i1 + 1]] 108 | dispXList.append([i1+1]+tempValueX) 109 | dispYList.append([i1 + 1] + tempValueY) 110 | dispZList.append([i1 + 1] + tempValueZ) 111 | return dispXList,dispYList,dispZList 112 | 113 | def intPointResponse(self,responseType): 114 | """ 115 | 提取积分点响应 116 | responseType:响应类型 117 | """ 118 | stepName, numSteps = self.steps 119 | returnDict = {} 120 | if responseType=='mises': 121 | for i1 in range(numSteps): 122 | flag = True 123 | j1 = 0 124 | while (flag): 125 | try: 126 | frame = self._odb.steps[stepName+"_" + str(i1 + 1)].frames[j1] 127 | j1 = j1 + 1 128 | displacement = frame.fieldOutputs['S'].values 129 | for each in displacement: 130 | if not returnDict.has_key(each.elementLabel): 131 | returnDict[each.elementLabel] = [] 132 | returnDict[each.elementLabel].append(each.mises) 133 | else: 134 | returnDict[each.elementLabel].append(each.mises) 135 | except: 136 | flag = False 137 | elif responseType=='PEEQ': 138 | for i1 in range(numSteps): 139 | flag = True 140 | j1 = 0 141 | while (flag): 142 | try: 143 | frame = self._odb.steps[stepName+"_" + str(i1 + 1)].frames[j1] 144 | j1 = j1 + 1 145 | displacement = frame.fieldOutputs['PEEQ'].values 146 | for each in displacement: 147 | if not returnDict.has_key(each.elementLabel): 148 | returnDict[each.elementLabel] = [] 149 | returnDict[each.elementLabel].append(each.data) 150 | else: 151 | returnDict[each.elementLabel].append(each.data) 152 | except: 153 | flag = False 154 | else: 155 | raise NameError("Please enter correct name:'mises' or'PEEQ'") 156 | num = len(returnDict) 157 | returnList = [] 158 | for i2 in range(num): 159 | numj = len(returnDict[i2 + 1]) / 2 160 | tempj = [returnDict[i2 + 1][2 * each] for each in range(numj)] 161 | returnList.append(([i2 + 1] + tempj)) 162 | return returnList 163 | ################################################################################ 164 | if __name__ == '__main__': 165 | odbPath = 'E:/abaqusModel/pythonProgramAbaqus/Job-pushOver.odb' 166 | instance=abaqusODBProcess(odbPath) 167 | ##节点及单元信息 168 | nodes=instance.nodes 169 | np.savetxt("postResults/nodes.txt",nodes,fmt='%d %.8f %.8f %.8f') 170 | elements=instance.elements 171 | np.savetxt("postResults/elements.txt", elements, fmt='%d') 172 | ##加载点力与位移时程 173 | nodedSetName = 'ASSEMBLY_CONSTRAINT-UPPERPLATE_REFERENCE_POINT' 174 | compDisp = 'U' 175 | comReactionForce = 'RF' 176 | rfDisp=instance.rfNodeResponse(nodedSetName,compDisp) 177 | np.savetxt('postResults/refDisp.txt',rfDisp,fmt='%f') 178 | rfForce = instance.rfNodeResponse(nodedSetName, comReactionForce) 179 | np.savetxt('postResults/refLoad.txt', rfForce, fmt='%f') 180 | ##节点位移时程 181 | dispXList, dispYList, dispZList = instance.nodeDisp() 182 | np.savetxt("postResults/dispX.txt",dispXList,fmt='%f') 183 | np.savetxt("postResults/dispY.txt",dispYList,fmt='%f') 184 | np.savetxt("postResults/dispZ.txt",dispZList,fmt='%f') 185 | ##单元积分点Mises应力 186 | responseType='mises' 187 | misesStress=instance.intPointResponse(responseType) 188 | np.savetxt("postResults/misesStress.txt", misesStress, fmt="%f") 189 | ##单元积分点等效塑性应变 190 | responseType1 = 'PEEQ' 191 | plasticStrain = instance.intPointResponse(responseType1) 192 | np.savetxt("postResults/PEEQ.txt", plasticStrain, fmt="%f") 193 | 194 | -------------------------------------------------------------------------------- /abaqusPythonScript.py: -------------------------------------------------------------------------------- 1 | import os 2 | ########################################################################## 3 | ########################---参数设置---#################################### 4 | thick=0.03 #弯曲板厚度(m) 5 | upperPlateThick=0.1 #上下固定板厚度 6 | height=1.5 #板高度(m) 7 | width=1.5 #板宽度(m) 8 | tapHeight=0.1 #不变宽度高度(m) 9 | middleHeight=0.3 #中间段高度(m) 10 | middleWidth=0.6 #中间段宽度(m) 11 | numPlate=5 #板个数(m) 12 | distance=0.2 #板间隔距离 13 | numStep=1 #荷载步数 14 | stepDisp=0.6 #每个荷载步位移增量 15 | seedSize=0.03 #网格尺寸 16 | maxInc=0.05 #每个荷载步增量大小 17 | ########################################################################## 18 | ########################---清除历史结果---################################# 19 | import fnmatch 20 | listName=os.listdir(os.getcwd()) 21 | for fileName in listName: 22 | try: 23 | if fnmatch.fnmatch(fileName,'Job-pushOver.*'): 24 | os.remove(fileName) 25 | except: 26 | os.system('taskkill /f /t /im '+"Job-pushOver.023") 27 | ########################################################################## 28 | ########################---abaqus脚本文件---############################## 29 | 30 | fileName="runAbaqus.py" 31 | os.remove(fileName) 32 | f= open(fileName, "a+") 33 | ####################################### 34 | #########---导入必要的模块---######### 35 | 36 | f.write( "#############################\n") 37 | f.write( "from abaqus import *\n") 38 | f.write( "from abaqusConstants import *\n") 39 | f.write( "from caeModules import *\n") 40 | f.write( "from odbAccess import *\n") 41 | f.write( "import regionToolset\n") 42 | # """ 43 | ###################################### 44 | #########---初始化---################# 45 | f.write( "#############################\n") 46 | f.write( "session.viewports[\"Viewport: 1\"].setValues(displayedObject=None)\n") 47 | ###################################### 48 | #########---建立模型---################ 49 | f.write( "#############################\n") 50 | f.write( "mdb.models.changeKey(fromName=\"Model-1\",toName=\"steelPlate Frame\")\n") 51 | f.write( "plateModel=mdb.models[\"steelPlate Frame\"]\n") 52 | ###################################### 53 | #########---生成部件---################ 54 | f.write( "#############################\n") 55 | f.write( "bendPlateSketch_1=plateModel.ConstrainedSketch(name=\"bendPlateSketch_1\",sheetSize=2)\n") 56 | xyCoords1=[(-0.5*width,tapHeight),(-0.5*width,0),(0.5*width,0),(0.5*width,tapHeight), 57 | (0.5*middleWidth,0.5*height-0.5*middleHeight),(0.5*middleWidth,0.5*height+0.5*middleHeight), 58 | (0.5*width,height-tapHeight),(0.5*width,height),(-0.5*width,height), 59 | (-0.5*width,height-tapHeight),(-0.5*middleWidth,0.5*height+0.5*middleHeight), 60 | (-0.5*middleWidth,0.5*height-0.5*middleHeight),(-0.5*width,tapHeight)] 61 | for j1 in range(len(xyCoords1)-1): 62 | f.write("bendPlateSketch_1.Line(point1="+str(xyCoords1[j1])+",point2="+str(xyCoords1[j1+1])+")\n") 63 | 64 | f.write( "bendPlatePart_1=plateModel.Part(name=\"bendPlatePart_1\",dimensionality=THREE_D,type=DEFORMABLE_BODY)\n") 65 | f.write( "bendPlatePart_1.BaseShell(sketch=bendPlateSketch_1)\n") 66 | for i1 in range(numPlate-1): 67 | f.write("bendPlatePart_"+str(i1+2)+"=plateModel.Part(name=\"bendPlatePart_"+ 68 | str(i1+2)+"\",objectToCopy=bendPlatePart_1)\n") 69 | #################### 70 | f.write( "bottomPlateSketch=plateModel.ConstrainedSketch(name=\"bottomPlate\",sheetSize=2)\n") 71 | xyCoords1=[(-0.5*width,0),(0.5*width,0)] 72 | extrudeValue=distance*(numPlate+1) 73 | f.write("bottomPlateSketch.Line(point1="+str(xyCoords1[0])+",point2="+str(xyCoords1[1])+")\n") 74 | f.write( "bottomPlatePart=plateModel.Part(name=\"bottomPlatePart\",dimensionality=THREE_D,type=DEFORMABLE_BODY)\n") 75 | f.write( "bottomPlatePart.BaseShellExtrude(sketch=bottomPlateSketch, depth="+str(extrudeValue)+")\n") 76 | f.write("upperPlatePart=plateModel.Part(name=\"upperPlatePart\",objectToCopy=bottomPlatePart)\n") 77 | ###################################### 78 | # """ 79 | #########---定义材料---################ 80 | f.write( "#############################\n") 81 | f.write( "elasPlasticMaterial=plateModel.Material(name=\"elasPlasticMaterial\")\n") 82 | f.write( "elasPlasticMaterial.Elastic(table=((210000000,0.3),))\n") 83 | stressStrainTable=((345000,0),(471000,0.15),(480000,1)) 84 | f.write( "elasPlasticMaterial.Plastic(table="+str(stressStrainTable)+")\n") 85 | ##################################### 86 | #########---创建截面---############### 87 | f.write( "#############################\n") 88 | f.write( "bendPlateSection=plateModel.HomogeneousShellSection(name=\"bendPlateSection\"," 89 | "material=\"elasPlasticMaterial\",thickness="+str(thick)+")\n") 90 | f.write( "fixPlateSection=plateModel.HomogeneousShellSection(name=\"fixPlateSection\"," 91 | "material=\"elasPlasticMaterial\",thickness="+str(upperPlateThick)+")\n") 92 | ##################################### 93 | #########---截面指定---############### 94 | f.write( "#############################\n") 95 | for i2 in range(numPlate): 96 | f.write("bendPlateFace_"+str(i2+1)+"=(bendPlatePart_"+str(i2+1)+".faces,)\n") 97 | f.write("bendPlatePart_"+str(i2+1)+".SectionAssignment(region=bendPlateFace_"+str(i2+1)+"," 98 | "sectionName=\"bendPlateSection\")\n") 99 | f.write("bottomPlateFaces=(bottomPlatePart.faces,)\n") 100 | f.write("bottomPlatePart.SectionAssignment(region=bottomPlateFaces,sectionName=\"fixPlateSection\")\n") 101 | f.write("upperPlateFaces=(upperPlatePart.faces,)\n") 102 | f.write("upperPlatePart.SectionAssignment(region=upperPlateFaces,sectionName=\"fixPlateSection\")\n") 103 | ###################################### 104 | #########---装配部件---############### 105 | f.write( "#############################\n") 106 | f.write("rootAssembly=plateModel.rootAssembly\n") 107 | for i3 in range(numPlate): 108 | f.write("bendInstance_"+str(i3+1)+"=rootAssembly.Instance(name=\"bendPlateAssembly_"+str(i3+1)+"\"," 109 | "part=bendPlatePart_"+str(i3+1)+",dependent=ON)\n") 110 | f.write("bottomInstance=rootAssembly.Instance(name=\"bottomPlateAssembly\",part=bottomPlatePart,dependent=ON)\n") 111 | f.write("upperInstance=rootAssembly.Instance(name=\"upperPlateAssembly\",part=upperPlatePart,dependent=ON)\n") 112 | for i4 in range(numPlate): 113 | f.write("rootAssembly.translate(instanceList=('bendPlateAssembly_"+str(i4+1)+"', )," 114 | " vector=(0.0, 0.0,"+str(distance*(i4+1))+"))\n") 115 | f.write("rootAssembly.translate(instanceList=('upperPlateAssembly', ), vector=(0.0,"+str(height)+",0.0))\n") 116 | 117 | f.write("assemblyPart=rootAssembly.InstanceFromBooleanMerge(name='assemblyPart', instances=(") 118 | for i5 in range(numPlate): 119 | f.write("bendInstance_"+str(i5+1)+",") 120 | f.write("\nbottomInstance,upperInstance,),originalInstances=SUPPRESS,domain=GEOMETRY)\n") 121 | ###################################### 122 | #########---荷载步设置---############## 123 | f.write( "#############################\n") 124 | aa="pushOver_"+str(1) 125 | f.write("plateModel.StaticStep(name=\""+aa+"\",previous='Initial', initialInc="+str(maxInc)+"," 126 | " maxInc="+str(maxInc)+",nlgeom=ON)\n") 127 | for i6 in range(numStep-1): 128 | previousName="pushOver_"+str(i6+1) 129 | currentName="pushOver_"+str(i6+2) 130 | f.write("plateModel.StaticStep(name=\"" + currentName + "\",previous=\"" + previousName + "\"," 131 | " initialInc="+str(maxInc)+", maxInc="+str(maxInc)+",nlgeom=ON)\n") 132 | ###################################### 133 | #########---耦合设置--############## 134 | f.write( "#############################\n") 135 | f.write("refPointid=rootAssembly.ReferencePoint(point="+str((0,height,0))+").id\n") 136 | f.write("refPointRegion=rootAssembly.Set(referencePoints=(rootAssembly.referencePoints[refPointid],), name='refPointSet')\n") 137 | points=tuple([((0,height,distance*(i7+0.5)),) for i7 in range(numPlate+1)]) 138 | f.write("assemblyTopFaces = assemblyPart.faces.findAt"+str(points)+"\n") 139 | f.write("topFameRegion=regionToolset.Region(faces=assemblyTopFaces)\n") 140 | f.write("plateModel.Coupling(name='Constraint-upperPlate',controlPoint=refPointRegion," 141 | "surface=topFameRegion,couplingType=KINEMATIC,influenceRadius=WHOLE_SURFACE)\n") 142 | ###################################### 143 | #########---边界条件设置--############# 144 | f.write( "#############################\n") 145 | pointsBC=tuple([((0,0,distance*(i7+0.5)),) for i7 in range(numPlate+1)]) 146 | f.write("assemblyBottomFaces = assemblyPart.faces.findAt"+str(pointsBC)+"\n") 147 | f.write("bottomFameRegion=regionToolset.Region(faces=assemblyBottomFaces)\n") 148 | f.write("plateModel.DisplacementBC(name='initBC', createStepName='Initial',region=bottomFameRegion," 149 | "u1=SET, u2=SET, u3=SET, ur1=SET,ur2=SET, ur3=SET)\n") 150 | ############################################# 151 | #########---pushOver荷载设置--################ 152 | f.write( "#############################\n") 153 | f.write("plateModel.DisplacementBC(name='pushOver',createStepName='pushOver_1',region=refPointRegion,u3="+str(stepDisp)+")\n") 154 | for i8 in range(numStep-1): 155 | stepName="pushOver_"+str(i8+2) 156 | u3=(i8+2)*stepDisp*(-1)**(i8+1) 157 | f.write("plateModel.boundaryConditions['pushOver'].setValuesInStep(stepName=\""+str(stepName)+"\",u3="+str(u3)+")\n") 158 | ############################################# 159 | #########---网格划分设置--#################### 160 | f.write( "#############################\n") 161 | ######网格尺寸设置 162 | f.write("meshPart=plateModel.parts[\"assemblyPart\"]\n") 163 | f.write("seedEdges=meshPart.edges\n") 164 | f.write("meshPart.seedEdgeBySize(edges=seedEdges,size="+str(seedSize)+")\n") 165 | ######划分控制设置 166 | f.write("assemblyFaces=assemblyPart.faces\n") 167 | f.write("assemblyFaces=meshPart.setMeshControls(regions=assemblyFaces,technique=STRUCTURED)\n") 168 | ######单元类型设置 169 | f.write("eleType1=mesh.ElemType(elemCode=S4R)\n") 170 | f.write("eleType2=mesh.ElemType(elemCode=S3)\n") 171 | f.write("meshRegion=regionToolset.Region(faces=(assemblyPart.faces),)\n") 172 | f.write("meshPart.setElementType(regions=meshRegion, elemTypes=(eleType1, eleType2))\n") 173 | ######网格划分 174 | f.write("meshPart.generateMesh()\n") 175 | ############################################# 176 | #########---任务设置--######################## 177 | f.write( "#############################\n") 178 | f.write("mdb.Job(name='Job-pushOver', model='steelPlate Frame', multiprocessingMode=DEFAULT, numCpus=4,numDomains=4, numGPUs=1)\n") 179 | f.write( "mdb.jobs['Job-pushOver'].submit(consistencyChecking=OFF)\n") 180 | # """ 181 | ###################################### 182 | f.close() 183 | ####################################### 184 | os.system('abaqus CAE script=runAbaqus.py') 185 | # os.system('abaqus CAE noGUI=runAbaqus.py') 186 | ############################################ 187 | ######结果数据库处理 188 | os.system('abaqus CAE noGUI=abaqusODBProcess.py') 189 | ########################################### 190 | ############################################ 191 | ######结果后处理 192 | 193 | -------------------------------------------------------------------------------- /dispForce.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Junjun1guo/pythonInteractAbaqus/364cf248b161bbd9760540cc86d4bd06d4eff667/dispForce.gif -------------------------------------------------------------------------------- /launcher.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | "C:\SIMULIA\Commands\abq2019.bat" %* -------------------------------------------------------------------------------- /main_Run.py: -------------------------------------------------------------------------------- 1 | #-*-coding: UTF-8-*- 2 | ######################################################################### 3 | # Author: Junjun Guo 4 | # E-mail: guojj@tongji.edu.cn/guojj_ce@163.com/guojj01@gmail.com 5 | # Environemet: Successfully executed in python 3.8 6 | # Date: 2021-09-19 7 | ######################################################################### 8 | #import necessary modules 9 | import os 10 | import runpy 11 | ######################################################################### 12 | ############---1---基于abaqus环境进行计算----########################## 13 | # os.system('abaqus CAE noGUI=runAbaqus.py') #active abaqus CAE and run the script 14 | os.system('abaqus CAE script=runAbaqus.py') #active abaqus CAE and run the script 15 | # print("Successfully executed runAbaqus.py module!") 16 | ############---2---操作obd文件提取结果----############################# 17 | # os.system('abaqus CAE noGUI=abaqusODBProcess.py') 18 | # os.system('abaqus CAE script=abaqusODBProcess.py') 19 | # print("Successfully executed abaqusODBProcess.py module!") 20 | ############---3---将提取的结果存储于数据库中----######################## 21 | # runpy.run_path('saveDataToSqlite.py', run_name='__main__') 22 | # print("Successfully executed saveDataToSqlite.py module!") 23 | ############---4---基于pyvista显示结果动图----######################## 24 | # runpy.run_path('resultsDisplayPyvista.py', run_name='__main__') 25 | # print("Successfully executed resultsDisplayPyvista.py module!") 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /misesStress.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Junjun1guo/pythonInteractAbaqus/364cf248b161bbd9760540cc86d4bd06d4eff667/misesStress.gif -------------------------------------------------------------------------------- /postResults/refDisp.txt: -------------------------------------------------------------------------------- 1 | 0.000000 0.000000 0.000000 2 | 0.000000 -0.000277 0.030000 3 | -0.000000 -0.001285 0.060000 4 | 0.000000 -0.002964 0.090000 5 | 0.000000 -0.005161 0.120000 6 | 0.000000 -0.007837 0.150000 7 | -0.000000 -0.011067 0.180000 8 | 0.000000 -0.014901 0.210000 9 | 0.000000 -0.019351 0.240000 10 | 0.000000 -0.024423 0.270000 11 | -0.000000 -0.030123 0.300000 12 | 0.000000 -0.036452 0.330000 13 | 0.000000 -0.043410 0.360000 14 | -0.000000 -0.050996 0.390000 15 | -0.000000 -0.059210 0.420000 16 | 0.000000 -0.068054 0.450000 17 | 0.000000 -0.070366 0.457500 18 | 0.000000 -0.072717 0.465000 19 | 0.000000 -0.076318 0.476250 20 | 0.000000 -0.081886 0.493125 21 | 0.000000 -0.090611 0.518438 22 | 0.000000 -0.099790 0.543750 23 | 0.000000 -0.109425 0.569062 24 | 0.000000 -0.119517 0.594375 25 | -0.000000 -0.121825 0.600000 26 | -------------------------------------------------------------------------------- /postResults/refLoad.txt: -------------------------------------------------------------------------------- 1 | 0.000000 0.000000 -0.000000 2 | 0.000000 0.000000 290.094574 3 | 0.000000 0.000000 568.478516 4 | 0.000000 0.000000 747.361511 5 | 0.000000 0.000000 845.071167 6 | 0.000000 0.000000 890.106873 7 | 0.000000 0.000000 912.915588 8 | 0.000000 0.000000 929.463135 9 | 0.000000 0.000000 943.338745 10 | 0.000000 0.000000 955.686157 11 | 0.000000 0.000000 967.042053 12 | 0.000000 0.000000 977.629578 13 | 0.000000 0.000000 987.638184 14 | 0.000000 0.000000 997.175903 15 | 0.000000 0.000000 1006.390808 16 | 0.000000 0.000000 1015.390076 17 | 0.000000 0.000000 1017.660217 18 | 0.000000 0.000000 1019.923645 19 | 0.000000 0.000000 1023.297424 20 | 0.000000 0.000000 1028.319214 21 | 0.000000 0.000000 1035.789917 22 | 0.000000 0.000000 1043.258545 23 | 0.000000 0.000000 1050.716187 24 | 0.000000 0.000000 1058.145996 25 | 0.000000 0.000000 1059.824341 26 | -------------------------------------------------------------------------------- /prePostProcess.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @File : 234.py 3 | # @Date : 2020-09-02 18:14 4 | # @Email : {guojj@tongji.edu.cn/guojj01@gmail.com} 5 | # @Author : guojj 6 | 7 | 8 | ###导入必要的模块 9 | import numpy as np 10 | import pyvista as pv 11 | import ctypes 12 | import os 13 | import time 14 | import array 15 | import re 16 | from saveDataToSqlite import SaveData 17 | 18 | class prePostPlot(object): 19 | """模型及结果显示类""" 20 | def __init__(self,dbPath): 21 | self.saveInstance = SaveData(dbPath) 22 | 23 | def prePlot(self): 24 | """前处理模型展示""" 25 | nodes=self.saveInstance.getAllNode() 26 | elements=self.saveInstance.getAllEle() 27 | nodesProcess=prePostPlot.strToListConvert(nodes,'coords','float') 28 | elementsProcess=prePostPlot.strToListConvert(elements,'connectivity','int') 29 | prePostPlot.staticPlot(nodesProcess,elementsProcess) 30 | 31 | def postPlot(self,comp,colorValue,saveName,sleepValue): 32 | """后处理结果绘制""" 33 | nodes = self.saveInstance.getAllNode() 34 | elements = self.saveInstance.getAllEle() 35 | nodesProcess = prePostPlot.strToListConvert(nodes, 'coords', 'float') 36 | elementsProcess = prePostPlot.strToListConvert(elements, 'connectivity', 'int') 37 | if comp=="mises": 38 | response=self.saveInstance.getAllMises() 39 | responsePorcess = prePostPlot.strToListConvert(response, 'mises', 'float') 40 | elif comp=="PEEQ": 41 | response = self.saveInstance.getAllPEEQ() 42 | responsePorcess = prePostPlot.strToListConvert(response, 'PEEQ', 'float') 43 | nodeDisp=self.saveInstance.getAllDisp() 44 | dispXProcess=prePostPlot.strToListConvert(nodeDisp, 'dispX', 'float') 45 | dispYProcess=prePostPlot.strToListConvert(nodeDisp, 'dispY', 'float') 46 | dispZProcess = prePostPlot.strToListConvert(nodeDisp, 'dispZ', 'float') 47 | prePostPlot.dynamicPlot(nodesProcess,elementsProcess,dispXProcess,dispYProcess 48 | ,dispZProcess,responsePorcess,colorValue,saveName,sleepValue) 49 | 50 | @staticmethod 51 | def dynamicPlot(nodes,elements,dispX,dispY,dispZ,varValue,colorValue,saveName,sleepValue): 52 | """""" 53 | ##绘图窗口设置 54 | user32 = ctypes.windll.user32 55 | screensizex, screensizey = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1) 56 | plotter = pv.Plotter(shape=(1,1), border=True, window_size=[int(screensizex), int(screensizey)]) 57 | plotter.set_background(color="white") 58 | ##数据格式处理 59 | vertices=np.array(nodes) 60 | elementProcess = [[len(each)] + list(map(lambda item: item - 1, each)) for each in elements] 61 | faces = np.hstack(elementProcess) 62 | surf = pv.PolyData(vertices, faces) 63 | scales = np.array([varValue[j1][0] for j1 in range(len(varValue))]) 64 | ##动态图绘制 65 | plotter.add_mesh(surf, show_edges=False, scalars=scales, edge_color="blue", interpolate_before_map=True, 66 | cmap="jet", clim=[0, colorValue], show_scalar_bar=True) 67 | plotter.show(interactive=False, auto_close=False) 68 | plotter.add_axes() 69 | plotter.camera_position = (2, 2, -2) 70 | plotter.open_gif(saveName+'.gif') 71 | for i1 in range(len(varValue[0]) - 1): 72 | scaless = np.array([varValue[j1][i1] for j1 in range(len(varValue))]) 73 | pts = np.array([[dispX[j1][i1] + vertices[j1][0], dispY[j1][i1] + vertices[j1][1], \ 74 | dispZ[j1][i1] + vertices[j1][2]] for j1 in range(len(dispX))]) 75 | plotter.update_scalars(scaless) 76 | plotter.update_coordinates(pts) 77 | plotter.write_frame() 78 | time.sleep(sleepValue) 79 | plotter.close() 80 | 81 | @staticmethod 82 | def staticPlot(nodes,elements,showNodes=False,showEle=False): 83 | """ 84 | 静态图形绘制 85 | """ 86 | vertices=np.array(nodes) 87 | elementProcess=[[len(each)]+list(map(lambda item:item-1,each)) for each in elements] 88 | faces=np.hstack(elementProcess) 89 | surf = pv.PolyData(vertices, faces) 90 | ##绘图窗口设置 91 | user32 = ctypes.windll.user32 92 | screensizex, screensizey = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1) 93 | plotter = pv.Plotter(shape=(1,1), border=True, window_size=[int(1 * screensizex), 94 | int(1 * screensizey)]) 95 | plotter.set_background(color="white") 96 | ##坐标轴绘制 97 | arrowX=pv.Arrow(start=(0,0,0),direction=(1,0,0),tip_length=0.3,tip_radius=0.1, 98 | shaft_radius=0.05,scale=0.1) 99 | arrowY=pv.Arrow(start=(0,0,0),direction=(0,1,0),tip_length=0.3,tip_radius=0.1, 100 | shaft_radius=0.05,scale=0.1) 101 | arrowZ=pv.Arrow(start=(0,0,0),direction=(0,0,1),tip_length=0.3,tip_radius=0.1, 102 | shaft_radius=0.05,scale=0.1) 103 | plotter.add_mesh(arrowX, color="red", show_edges=False) 104 | plotter.add_mesh(arrowY, color="green", show_edges=False) 105 | plotter.add_mesh(arrowZ, color="blue", show_edges=False) 106 | ##图形绘制 107 | plotter.add_mesh(surf, show_edges=True, edge_color="blue",style='surface') 108 | if showNodes==True: 109 | labelRange = [(i1 + 1) for i1 in range(len(vertices))] 110 | plotter.add_point_labels(vertices,labelRange, bold=False, point_size=0, 111 | font_size=16,text_color="red",font_family="times",show_points=False,shape=None,tolerance=1.0) 112 | if showEle==True: 113 | pass 114 | plotter.show(interactive=True, auto_close=False) 115 | 116 | @staticmethod 117 | def strToListConvert(strList,keys,types): 118 | """ 119 | pass 120 | 将字符化列表转为数字列表,'[1,2,3]'to [1,2,3] 121 | 其中strList为字典列表,keys为键值,types为转换目标类型 122 | """ 123 | temp1=[each[keys][1:-1].split() for each in strList] 124 | returnList=[list(map(float,each)) for each in temp1] 125 | if types=='float': 126 | finalList=returnList 127 | elif types=='int': 128 | finalList=[list(map(eval(types),each)) for each in returnList] 129 | else: 130 | print("types must be float or int!") 131 | return finalList 132 | 133 | @staticmethod 134 | def intervalValue(maxValue,numbers): 135 | """ 136 | 返回间隔线间隔大小 137 | maxValue-最大值 138 | numbers-分割线个数 139 | """ 140 | b = len(str(int(maxValue))) 141 | if b==1 and int(maxValue)==0: 142 | interval = round(maxValue /numbers, 2) 143 | i3=2 144 | while(interval==0): 145 | interval=round(maxValue /numbers, i3+1) 146 | i3=i3+1 147 | 148 | elif b==1 and int(maxValue)!=0: 149 | interval = int(maxValue /numbers) 150 | else: 151 | loc = maxValue / 10 ** (b - 1) 152 | interval = int(loc) * 0.2 * 10 ** (b - 1) 153 | return interval 154 | 155 | def dispForcePlot(self,saveName,timeSleep,disp=None,force=None): 156 | """滞回曲线绘制""" 157 | if disp==None and force==None: 158 | dispForce= self.saveInstance.getRefResponse() 159 | dispX= np.array(prePostPlot.strToListConvert(dispForce, 'refDisp', 'float'))[:,2] 160 | forceY = np.array(prePostPlot.strToListConvert(dispForce, 'refLoad', 'float'))[:, 2] 161 | else: 162 | dispX=disp 163 | forceY=force 164 | ###绘图窗口设置 165 | 166 | user32 = ctypes.windll.user32 167 | screensizex, screensizey = 0.9*user32.GetSystemMetrics(0), 0.9*user32.GetSystemMetrics(1) 168 | plotter = pv.Plotter(shape=(1, 1), border=True, window_size=[int(screensizex), int(screensizey)]) 169 | plotter.set_background(color="white") 170 | ###数据格式处理 171 | maxDisp=1.1*max(np.abs(dispX)) 172 | maxForce = max(np.abs(forceY)) 173 | screenRatio=user32.GetSystemMetrics(0)/float(user32.GetSystemMetrics(1)) 174 | ratio=screenRatio*maxForce/float(maxDisp) 175 | ###坐标轴绘制 176 | plotter.camera_position = [(0, 0, 5 * maxForce), (0, 0, 0), (0, 1, 0)] 177 | lineX= np.array([[-1.2*ratio*maxDisp,0, 0], [1.2*ratio*maxDisp,0, 0]]) 178 | arrayXUp= np.array([[1.15*ratio*maxDisp,0.02*maxForce, 0], [1.2*ratio*maxDisp,0, 0]]) 179 | arrayXDown = np.array([[1.15 * ratio * maxDisp, -0.02 * maxForce, 0], [1.2 * ratio * maxDisp, 0, 0]]) 180 | lineY = np.array([[0, -1.2*maxForce, 0], [0, 1.2*maxForce, 0]]) 181 | arrayYLeft = np.array([[-0.02*maxForce, 1.12*maxForce, 0], [0, 1.2*maxForce, 0]]) 182 | arrayYRight = np.array([[0.02 * maxForce, 1.12 * maxForce, 0], [0, 1.2 * maxForce, 0]]) 183 | plotter.add_lines(lineX, color="k", width=2) 184 | plotter.add_lines(lineY, color="k", width=2) 185 | plotter.add_lines(arrayXUp, color="k", width=2) 186 | plotter.add_lines(arrayXDown, color="k", width=2) 187 | plotter.add_lines(arrayYLeft, color="k", width=2) 188 | plotter.add_lines(arrayYRight, color="k", width=2) 189 | ###坐标标签绘制 190 | plotter.add_point_labels(np.array([1.8*maxForce,-0.1*maxForce,0]),labels=["disp. (m)"], 191 | text_color="red",font_size=20,font_family='times',fill_shape=False, 192 | shape=None) 193 | plotter.add_point_labels(np.array([-0.4*maxForce, 1.12* maxForce, 0]), labels=["force (kN)"], 194 | text_color="red", font_size=20, font_family='times', fill_shape=False, 195 | shape=None) 196 | ###间隔大小 197 | intervalX=prePostPlot.intervalValue(maxDisp,5) 198 | intervalY = prePostPlot.intervalValue(maxForce, 5) 199 | ###分割线绘制 200 | bottomLine=np.array([[-1*ratio*maxDisp,-1.1*maxForce, 0], [1*ratio*maxDisp,-1.1*maxForce, 0]]) 201 | upLine = np.array([[-1 * ratio * maxDisp, 1.1 * maxForce, 0], [1 * ratio * maxDisp, 1.1 * maxForce, 0]]) 202 | leftLine = np.array([[-1 * ratio * maxDisp, -1.1 * maxForce, 0], [-1 * ratio * maxDisp, 1.1 *maxForce, 0]]) 203 | rightLine = np.array([[1 * ratio * maxDisp, -1.1 * maxForce, 0], [1 * ratio * maxDisp, 1.1 * maxForce, 0]]) 204 | plotter.add_lines(bottomLine, color="k", width=1) 205 | plotter.add_lines(upLine, color="k", width=1) 206 | plotter.add_lines(leftLine, color="k", width=1) 207 | plotter.add_lines(rightLine, color="k", width=1) 208 | 209 | indexX=0 210 | while((indexX*intervalX)<(maxDisp-intervalX)): 211 | indexX=indexX+1 212 | posVertical = np.array([[ratio*intervalX*indexX, -1.1 * maxForce, 0], 213 | [ratio*intervalX*indexX, 1.1 * maxForce, 0]]) 214 | negVertical = np.array([[-ratio*intervalX * indexX, -1.1 * maxForce, 0], 215 | [-ratio*intervalX * indexX, 1.1 * maxForce, 0]]) 216 | plotter.add_lines(posVertical, color="grey", width=0.1) 217 | plotter.add_lines(negVertical, color="grey", width=0.1) 218 | textPos=ratio*intervalX*(indexX-1) 219 | plotter.add_point_labels(np.array([textPos+0.8*intervalX*ratio, -1.2 * maxForce, 0]), 220 | labels=[str(intervalX*indexX)], text_color="k", font_size=15, 221 | font_family='times', fill_shape=False, shape=None) 222 | plotter.add_point_labels(np.array([-textPos -1.2 * intervalX * ratio, -1.2 * maxForce, 0]), 223 | labels=[str(-intervalX * indexX)], text_color="k", font_size=15, 224 | font_family='times', fill_shape=False, shape=None) 225 | plotter.add_point_labels(np.array([maxForce*0.01, -1.2 * maxForce, 0]), 226 | labels=[str(0)], text_color="k", font_size=15, 227 | font_family='times', fill_shape=False, shape=None) 228 | 229 | indexY = 0 230 | while ((indexY * intervalY) < (maxForce-intervalY)): 231 | indexY = indexY + 1 232 | posHorizontal = np.array([[-1 * ratio * maxDisp, indexY*intervalY, 0], 233 | [1 * ratio * maxDisp, indexY*intervalY, 0]]) 234 | negHorizontal = np.array([[-1 * ratio * maxDisp, -indexY * intervalY, 0], 235 | [1 * ratio * maxDisp, -indexY * intervalY, 0]]) 236 | plotter.add_lines(posHorizontal, color="grey", width=0.1) 237 | plotter.add_lines(negHorizontal, color="grey", width=0.1) 238 | textPos = intervalY * (indexY - 1) 239 | plotter.add_point_labels(np.array([-1.15 * ratio * maxDisp, textPos+0.9*intervalY, 0]), 240 | labels=[str(intervalY*indexY)],text_color="k", font_size=15, 241 | font_family='times', fill_shape=False,shape=None) 242 | plotter.add_point_labels(np.array([-1.15 * ratio * maxDisp, -textPos-1.1*intervalY, 0]), 243 | labels=[str(-intervalY * indexY)], text_color="k", font_size=15, 244 | font_family='times', fill_shape=False, shape=None) 245 | plotter.add_point_labels(np.array([-1.15 * ratio * maxDisp, maxForce*0.01, 0]), 246 | labels=[str(0.0)], text_color="k", font_size=15, 247 | font_family='times', fill_shape=False, shape=None) 248 | ###动态图绘制 249 | plotter.show(interactive=False, auto_close=False) 250 | plotter.open_gif(str(saveName)+'.gif') 251 | num=len(dispX)-1 252 | for i1 in range(num): 253 | lines=np.array([[ratio*dispX[i1],forceY[i1],0], [ratio*dispX[i1+1],forceY[i1+1],0]]) 254 | plotter.add_lines(lines,color="red",width=2) 255 | plotter.write_frame() 256 | time.sleep(timeSleep) 257 | ################################################################################ 258 | if __name__ == '__main__': 259 | dbPath="postResultDB.db" 260 | instance=prePostPlot(dbPath) 261 | instance.prePlot() 262 | componentMame="mises" 263 | colorValue=371000 264 | saveName="plasticStrain" 265 | timeSleep=0.1 266 | instance.postPlot(componentMame,colorValue,saveName,timeSleep) #绘制应力及等效塑性应变动态图 267 | saveName1="dispForce" 268 | instance.dispForcePlot(saveName1,timeSleep) #绘制加载点力与位移滞回曲线 269 | 270 | -------------------------------------------------------------------------------- /prePostProcess.py.bak: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @File : 234.py 3 | # @Date : 2020-09-02 18:14 4 | # @Email : {guojj@tongji.edu.cn/guojj01@gmail.com} 5 | # @Author : guojj 6 | 7 | 8 | ###导入必要的模块 9 | import numpy as np 10 | import pyvista as pv 11 | import pygmsh 12 | import ctypes 13 | import os 14 | import shutil 15 | import time 16 | import pyqtgraph as pg 17 | import array 18 | from numba import jit 19 | import meshio 20 | import re 21 | import json 22 | from saveDataToSqlite import SaveData 23 | 24 | class prePostPlot(object): 25 | """模型及结果显示类""" 26 | def __init__(self,dbPath): 27 | self.saveInstance = SaveData(dbPath) 28 | 29 | def prePlot(self): 30 | """前处理模型展示""" 31 | nodes=self.saveInstance.getAllNode() 32 | elements=self.saveInstance.getAllEle() 33 | nodesProcess=prePostPlot.strToListConvert(nodes,'coords','float') 34 | elementsProcess=prePostPlot.strToListConvert(elements,'connectivity','int') 35 | prePostPlot.staticPlot(nodesProcess,elementsProcess) 36 | 37 | def postPlot(self,comp,colorValue,saveName,sleepValue): 38 | """后处理结果绘制""" 39 | nodes = self.saveInstance.getAllNode() 40 | elements = self.saveInstance.getAllEle() 41 | nodesProcess = prePostPlot.strToListConvert(nodes, 'coords', 'float') 42 | elementsProcess = prePostPlot.strToListConvert(elements, 'connectivity', 'int') 43 | if comp=="mises": 44 | response=self.saveInstance.getAllMises() 45 | responsePorcess = prePostPlot.strToListConvert(response, 'mises', 'float') 46 | elif comp=="PEEQ": 47 | response = self.saveInstance.getAllPEEQ() 48 | responsePorcess = prePostPlot.strToListConvert(response, 'PEEQ', 'float') 49 | nodeDisp=self.saveInstance.getAllDisp() 50 | dispXProcess=prePostPlot.strToListConvert(nodeDisp, 'dispX', 'float') 51 | dispYProcess=prePostPlot.strToListConvert(nodeDisp, 'dispY', 'float') 52 | dispZProcess = prePostPlot.strToListConvert(nodeDisp, 'dispZ', 'float') 53 | prePostPlot.dynamicPlot(nodesProcess,elementsProcess,dispXProcess,dispYProcess 54 | ,dispZProcess,responsePorcess,colorValue,saveName,sleepValue) 55 | 56 | @staticmethod 57 | def dynamicPlot(nodes,elements,dispX,dispY,dispZ,varValue,colorValue,saveName,sleepValue): 58 | """""" 59 | ##绘图窗口设置 60 | user32 = ctypes.windll.user32 61 | screensizex, screensizey = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1) 62 | plotter = pv.Plotter(shape=(1,1), border=True, window_size=[int(screensizex), int(screensizey)]) 63 | plotter.set_background(color="white") 64 | ##数据格式处理 65 | vertices=np.array(nodes) 66 | elementProcess = [[len(each)] + list(map(lambda item: item - 1, each)) for each in elements] 67 | faces = np.hstack(elementProcess) 68 | surf = pv.PolyData(vertices, faces) 69 | scales = np.array([varValue[j1][0] for j1 in range(len(varValue))]) 70 | ##动态图绘制 71 | plotter.add_mesh(surf, show_edges=False, scalars=scales, edge_color="blue", interpolate_before_map=True, 72 | cmap="jet", clim=[0, colorValue], show_scalar_bar=True) 73 | plotter.show(interactive=False, auto_close=False) 74 | plotter.add_axes() 75 | plotter.camera_position = (2, 2, -2) 76 | plotter.open_gif(saveName+'.gif') 77 | for i1 in range(len(varValue[0]) - 1): 78 | scaless = np.array([varValue[j1][i1] for j1 in range(len(varValue))]) 79 | pts = np.array([[dispX[j1][i1] + vertices[j1][0], dispY[j1][i1] + vertices[j1][1], \ 80 | dispZ[j1][i1] + vertices[j1][2]] for j1 in range(len(dispX))]) 81 | plotter.update_scalars(scaless) 82 | plotter.update_coordinates(pts) 83 | plotter.write_frame() 84 | time.sleep(sleepValue) 85 | plotter.close() 86 | 87 | @staticmethod 88 | def staticPlot(nodes,elements,showNodes=False,showEle=False): 89 | """ 90 | 静态图形绘制 91 | """ 92 | vertices=np.array(nodes) 93 | elementProcess=[[len(each)]+list(map(lambda item:item-1,each)) for each in elements] 94 | faces=np.hstack(elementProcess) 95 | surf = pv.PolyData(vertices, faces) 96 | ##绘图窗口设置 97 | user32 = ctypes.windll.user32 98 | screensizex, screensizey = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1) 99 | plotter = pv.Plotter(shape=(1,1), border=True, window_size=[int(1 * screensizex), 100 | int(1 * screensizey)]) 101 | plotter.set_background(color="white") 102 | ##坐标轴绘制 103 | arrowX=pv.Arrow(start=(0,0,0),direction=(1,0,0),tip_length=0.3,tip_radius=0.1, 104 | shaft_radius=0.05,scale=0.1) 105 | arrowY=pv.Arrow(start=(0,0,0),direction=(0,1,0),tip_length=0.3,tip_radius=0.1, 106 | shaft_radius=0.05,scale=0.1) 107 | arrowZ=pv.Arrow(start=(0,0,0),direction=(0,0,1),tip_length=0.3,tip_radius=0.1, 108 | shaft_radius=0.05,scale=0.1) 109 | plotter.add_mesh(arrowX, color="red", show_edges=False) 110 | plotter.add_mesh(arrowY, color="green", show_edges=False) 111 | plotter.add_mesh(arrowZ, color="blue", show_edges=False) 112 | ##图形绘制 113 | plotter.add_mesh(surf, show_edges=True, edge_color="blue",style='surface') 114 | if showNodes==True: 115 | labelRange = [(i1 + 1) for i1 in range(len(vertices))] 116 | plotter.add_point_labels(vertices,labelRange, bold=False, point_size=0, 117 | font_size=16,text_color="red",font_family="times",show_points=False,shape=None,tolerance=1.0) 118 | if showEle==True: 119 | pass 120 | plotter.show(interactive=True, auto_close=False) 121 | 122 | @staticmethod 123 | def strToListConvert(strList,keys,types): 124 | """ 125 | pass 126 | 将字符化列表转为数字列表,'[1,2,3]'to [1,2,3] 127 | 其中strList为字典列表,keys为键值,types为转换目标类型 128 | """ 129 | temp1=[each[keys][1:-1].split() for each in strList] 130 | returnList=[list(map(float,each)) for each in temp1] 131 | if types=='float': 132 | finalList=returnList 133 | elif types=='int': 134 | finalList=[list(map(eval(types),each)) for each in returnList] 135 | else: 136 | print("types must be float or int!") 137 | return finalList 138 | 139 | @staticmethod 140 | def intervalValue(maxValue,numbers): 141 | """ 142 | 返回间隔线间隔大小 143 | maxValue-最大值 144 | numbers-分割线个数 145 | """ 146 | b = len(str(int(maxValue))) 147 | if b==1 and int(maxValue)==0: 148 | interval = round(maxValue /numbers, 2) 149 | i3=2 150 | while(interval==0): 151 | interval=round(maxValue /numbers, i3+1) 152 | i3=i3+1 153 | 154 | elif b==1 and int(maxValue)!=0: 155 | interval = int(maxValue /numbers) 156 | else: 157 | loc = maxValue / 10 ** (b - 1) 158 | interval = int(loc) * 0.2 * 10 ** (b - 1) 159 | return interval 160 | 161 | def dispForcePlot(self,saveName,timeSleep,disp=None,force=None): 162 | """滞回曲线绘制""" 163 | if disp==None and force==None: 164 | dispForce= self.saveInstance.getRefResponse() 165 | dispX= np.array(prePostPlot.strToListConvert(dispForce, 'refDisp', 'float'))[:,2] 166 | forceY = np.array(prePostPlot.strToListConvert(dispForce, 'refLoad', 'float'))[:, 2] 167 | else: 168 | dispX=disp 169 | forceY=force 170 | ###绘图窗口设置 171 | 172 | user32 = ctypes.windll.user32 173 | screensizex, screensizey = 0.9*user32.GetSystemMetrics(0), 0.9*user32.GetSystemMetrics(1) 174 | plotter = pv.Plotter(shape=(1, 1), border=True, window_size=[int(screensizex), int(screensizey)]) 175 | plotter.set_background(color="white") 176 | ###数据格式处理 177 | maxDisp=1.1*max(np.abs(dispX)) 178 | maxForce = max(np.abs(forceY)) 179 | screenRatio=user32.GetSystemMetrics(0)/float(user32.GetSystemMetrics(1)) 180 | ratio=screenRatio*maxForce/float(maxDisp) 181 | ###坐标轴绘制 182 | plotter.camera_position = [(0, 0, 5 * maxForce), (0, 0, 0), (0, 1, 0)] 183 | lineX= np.array([[-1.2*ratio*maxDisp,0, 0], [1.2*ratio*maxDisp,0, 0]]) 184 | arrayXUp= np.array([[1.15*ratio*maxDisp,0.02*maxForce, 0], [1.2*ratio*maxDisp,0, 0]]) 185 | arrayXDown = np.array([[1.15 * ratio * maxDisp, -0.02 * maxForce, 0], [1.2 * ratio * maxDisp, 0, 0]]) 186 | lineY = np.array([[0, -1.2*maxForce, 0], [0, 1.2*maxForce, 0]]) 187 | arrayYLeft = np.array([[-0.02*maxForce, 1.12*maxForce, 0], [0, 1.2*maxForce, 0]]) 188 | arrayYRight = np.array([[0.02 * maxForce, 1.12 * maxForce, 0], [0, 1.2 * maxForce, 0]]) 189 | plotter.add_lines(lineX, color="k", width=2) 190 | plotter.add_lines(lineY, color="k", width=2) 191 | plotter.add_lines(arrayXUp, color="k", width=2) 192 | plotter.add_lines(arrayXDown, color="k", width=2) 193 | plotter.add_lines(arrayYLeft, color="k", width=2) 194 | plotter.add_lines(arrayYRight, color="k", width=2) 195 | ###坐标标签绘制 196 | plotter.add_point_labels(np.array([1.8*maxForce,-0.1*maxForce,0]),labels=["disp. (m)"], 197 | text_color="red",font_size=20,font_family='times',fill_shape=False, 198 | shape=None) 199 | plotter.add_point_labels(np.array([-0.4*maxForce, 1.12* maxForce, 0]), labels=["force (kN)"], 200 | text_color="red", font_size=20, font_family='times', fill_shape=False, 201 | shape=None) 202 | ###间隔大小 203 | intervalX=prePostPlot.intervalValue(maxDisp,5) 204 | intervalY = prePostPlot.intervalValue(maxForce, 5) 205 | ###分割线绘制 206 | bottomLine=np.array([[-1*ratio*maxDisp,-1.1*maxForce, 0], [1*ratio*maxDisp,-1.1*maxForce, 0]]) 207 | upLine = np.array([[-1 * ratio * maxDisp, 1.1 * maxForce, 0], [1 * ratio * maxDisp, 1.1 * maxForce, 0]]) 208 | leftLine = np.array([[-1 * ratio * maxDisp, -1.1 * maxForce, 0], [-1 * ratio * maxDisp, 1.1 *maxForce, 0]]) 209 | rightLine = np.array([[1 * ratio * maxDisp, -1.1 * maxForce, 0], [1 * ratio * maxDisp, 1.1 * maxForce, 0]]) 210 | plotter.add_lines(bottomLine, color="k", width=1) 211 | plotter.add_lines(upLine, color="k", width=1) 212 | plotter.add_lines(leftLine, color="k", width=1) 213 | plotter.add_lines(rightLine, color="k", width=1) 214 | 215 | indexX=0 216 | while((indexX*intervalX)<(maxDisp-intervalX)): 217 | indexX=indexX+1 218 | posVertical = np.array([[ratio*intervalX*indexX, -1.1 * maxForce, 0], 219 | [ratio*intervalX*indexX, 1.1 * maxForce, 0]]) 220 | negVertical = np.array([[-ratio*intervalX * indexX, -1.1 * maxForce, 0], 221 | [-ratio*intervalX * indexX, 1.1 * maxForce, 0]]) 222 | plotter.add_lines(posVertical, color="grey", width=0.1) 223 | plotter.add_lines(negVertical, color="grey", width=0.1) 224 | textPos=ratio*intervalX*(indexX-1) 225 | plotter.add_point_labels(np.array([textPos+0.8*intervalX*ratio, -1.2 * maxForce, 0]), 226 | labels=[str(intervalX*indexX)], text_color="k", font_size=15, 227 | font_family='times', fill_shape=False, shape=None) 228 | plotter.add_point_labels(np.array([-textPos -1.2 * intervalX * ratio, -1.2 * maxForce, 0]), 229 | labels=[str(-intervalX * indexX)], text_color="k", font_size=15, 230 | font_family='times', fill_shape=False, shape=None) 231 | plotter.add_point_labels(np.array([maxForce*0.01, -1.2 * maxForce, 0]), 232 | labels=[str(0)], text_color="k", font_size=15, 233 | font_family='times', fill_shape=False, shape=None) 234 | 235 | indexY = 0 236 | while ((indexY * intervalY) < (maxForce-intervalY)): 237 | indexY = indexY + 1 238 | posHorizontal = np.array([[-1 * ratio * maxDisp, indexY*intervalY, 0], 239 | [1 * ratio * maxDisp, indexY*intervalY, 0]]) 240 | negHorizontal = np.array([[-1 * ratio * maxDisp, -indexY * intervalY, 0], 241 | [1 * ratio * maxDisp, -indexY * intervalY, 0]]) 242 | plotter.add_lines(posHorizontal, color="grey", width=0.1) 243 | plotter.add_lines(negHorizontal, color="grey", width=0.1) 244 | textPos = intervalY * (indexY - 1) 245 | plotter.add_point_labels(np.array([-1.15 * ratio * maxDisp, textPos+0.9*intervalY, 0]), 246 | labels=[str(intervalY*indexY)],text_color="k", font_size=15, 247 | font_family='times', fill_shape=False,shape=None) 248 | plotter.add_point_labels(np.array([-1.15 * ratio * maxDisp, -textPos-1.1*intervalY, 0]), 249 | labels=[str(-intervalY * indexY)], text_color="k", font_size=15, 250 | font_family='times', fill_shape=False, shape=None) 251 | plotter.add_point_labels(np.array([-1.15 * ratio * maxDisp, maxForce*0.01, 0]), 252 | labels=[str(0.0)], text_color="k", font_size=15, 253 | font_family='times', fill_shape=False, shape=None) 254 | ###动态图绘制 255 | plotter.show(interactive=False, auto_close=False) 256 | plotter.open_gif(str(saveName)+'.gif') 257 | num=len(dispX)-1 258 | for i1 in range(num): 259 | lines=np.array([[ratio*dispX[i1],forceY[i1],0], [ratio*dispX[i1+1],forceY[i1+1],0]]) 260 | plotter.add_lines(lines,color="red",width=2) 261 | plotter.write_frame() 262 | time.sleep(timeSleep) 263 | ################################################################################ 264 | if __name__ == '__main__': 265 | dbPath="postResultDB.db" 266 | instance=prePostPlot(dbPath) 267 | # # instance.prePlot() 268 | componentMame="mises" 269 | colorValue=371000 270 | saveName="plasticStrain" 271 | timeSleep=0.1 272 | instance.postPlot(componentMame,colorValue,saveName,timeSleep) 273 | saveName1="dispForce" 274 | instance.dispForcePlot(saveName1,timeSleep) 275 | 276 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyvista==0.25.3 2 | records==0.5.3 3 | numpy==1.19.1 4 | -------------------------------------------------------------------------------- /runAbaqus.py: -------------------------------------------------------------------------------- 1 | #-*-coding: UTF-8-*- 2 | #####Units: Length-m, Force-kN, mass-ton, Stress-kpa(10e-3MPa), g=9.81m/s2 3 | #####Units: Length-mm, Force-N, mass-ton, Stress-Mpa, g=9810mm/s2 pho=ton/mm3 4 | ######################################################################### 5 | # Author: Junjun Guo 6 | # E-mail: guojj@tongji.edu.cn/guojj_ce@163.com/guojj01@gmail.com 7 | # Environemet: Successfully executed in python 3.8 8 | # Date: 2021-09-19 9 | ######################################################################### 10 | ########################---导入必要模块---################################# 11 | import os 12 | import shutil 13 | import numpy as np 14 | from abaqus import * 15 | from abaqusConstants import *#导入abaqus常量 16 | from symbolicConstants import *#导入abaqus符号常量 17 | from caeModules import *#导入CAE各模块 18 | from odbAccess import *#odb操作模块 19 | import regionToolset#集合选择 20 | ###########---1---基于abaqus环境进行计算----################################# 21 | numStep=10 #荷载步数 22 | maxInc=0.05 #每个荷载步增量大小,总量为1 23 | stepDisp=20 #每个荷载步位移大小(mm) 24 | PlateSeedSize=5 #钢板网格尺寸(mm) 25 | RodSeedSize=5 #连接杆网格尺寸(mm) 26 | trianglePlateTopWidth=100 #钢板顶边宽度(mm) 27 | trianglePlateBottomWidth=500#梯形钢板底部宽度(mm) 28 | trianglePlateHeight=600#梯形钢板高度(mm) 29 | rodRaidus=20#连接杆半径(mm) 30 | fy=406.307 #钢材屈服强度(Mpa) 31 | fu=723.320 #钢材极限强度(Mpa) 32 | E=1.91E+05 #钢材弹性模量(Mpa) 33 | epsilon=0.103 #最大强度对应的应变 34 | shellThinkness=15 ##三角钢板厚度(mm) 35 | slotHeight=100 #滑槽内部高度(mm) 36 | slotThickness=20#滑槽厚度(mm) 37 | slotDepth=200 #滑槽深度(mm) 38 | ######################################################################### 39 | ########################---清除历史结果---################################# 40 | import fnmatch #用于文件名称匹配 41 | listName=os.listdir(os.getcwd())#获取当前文件夹路文件目录 42 | for fileName in listName: 43 | try: 44 | if fnmatch.fnmatch(fileName,'Job-pushOver.*'): 45 | os.remove(fileName)#清除历史abaqus数据 46 | except: 47 | os.system('taskkill /f /t /im '+"Job-pushOver.023")#杀死进程中abaqus任务 48 | ########################################################################## 49 | ###########################---初始化模型---################################# 50 | session.viewports["Viewport: 1"].setValues(displayedObject=None)#视图设置 51 | mdb.models.changeKey(fromName="Model-1",toName="selfCenteringSteelDamper")#修改模型名称 52 | steelDamperModel=mdb.models["selfCenteringSteelDamper"]#模型变量 53 | ######################################################################### 54 | ###########################---生成部件---################################## 55 | ####---三角钢板--- 56 | trianglePlateSketch_1=steelDamperModel.ConstrainedSketch(name="trianglePlateSketch_1",sheetSize=2000)#设置草图绘制 57 | trianglePlateSketch_1.Line(point1=(0,0),point2=(trianglePlateBottomWidth, 0)) 58 | upperCoord=(trianglePlateBottomWidth-trianglePlateTopWidth)*0.5 59 | trianglePlateSketch_1.Line(point1=(trianglePlateBottomWidth, 0),point2=(trianglePlateBottomWidth-upperCoord,trianglePlateHeight)) 60 | trianglePlateSketch_1.Line(point1=(trianglePlateBottomWidth-upperCoord,trianglePlateHeight),point2=(upperCoord,trianglePlateHeight)) 61 | trianglePlateSketch_1.Line(point1=(upperCoord,trianglePlateHeight),point2=(0, 0)) 62 | trianglePlatePart_1=steelDamperModel.Part(name="trianglePlatePart_1",dimensionality=THREE_D,type=DEFORMABLE_BODY)#生成部件 63 | trianglePlatePart_1.BaseShell(sketch=trianglePlateSketch_1)#生成部件壳体 64 | ####---连接杆--- 65 | connectingRodSketch=steelDamperModel.ConstrainedSketch(name="connectingRodSketch",sheetSize=2000)#设置草图绘制 66 | connectingRodSketch.CircleByCenterPerimeter(center=(0.0, 0.0), point1=(0.0,rodRaidus)) 67 | connectingRodPart=steelDamperModel.Part(name="connectingRodPart",dimensionality=THREE_D,type=DEFORMABLE_BODY) 68 | connectingRodPart.BaseSolidExtrude(sketch=connectingRodSketch, depth=trianglePlateTopWidth) 69 | ####---滑槽--- 70 | connectingSlotSketch=steelDamperModel.ConstrainedSketch(name="connectingSlotSketch",sheetSize=2000)#设置草图绘制 71 | connectingSlotSketch.Line(point1=(0,0),point2=(slotThickness, 0)) 72 | connectingSlotSketch.Line(point1=(slotThickness, 0),point2=(slotThickness, slotHeight)) 73 | connectingSlotSketch.Line(point1=(slotThickness, slotHeight),point2=(slotThickness+rodRaidus*2, slotHeight)) 74 | connectingSlotSketch.Line(point1=(slotThickness+rodRaidus*2, slotHeight),point2=(slotThickness+rodRaidus*2,0)) 75 | connectingSlotSketch.Line(point1=(slotThickness+rodRaidus*2,0),point2=(slotThickness*2+rodRaidus*2, 0)) 76 | connectingSlotSketch.Line(point1=(slotThickness*2+rodRaidus*2, 0),point2=(slotThickness*2+rodRaidus*2,slotHeight+slotThickness)) 77 | connectingSlotSketch.Line(point1=(slotThickness*2+rodRaidus*2,slotHeight+slotThickness), 78 | point2=(0,slotHeight+slotThickness)) 79 | connectingSlotSketch.Line(point1=(0,slotHeight+slotThickness),point2=(0,0)) 80 | slotPart=steelDamperModel.Part(name="slotPart",dimensionality=THREE_D,type=DEFORMABLE_BODY)#生成部件 81 | slotPart.BaseSolidExtrude(sketch=connectingSlotSketch, depth=slotDepth) 82 | ######################################################################### 83 | ###########################---材料定义---################################## 84 | ####---弹性材料--- 85 | elasticMaterial=steelDamperModel.Material(name="elasticMaterial")#线弹性材料名称定义 86 | elasticMaterial.Elastic(table=((E, 0.3), ))#线弹性材料定义 87 | ####---弹塑性材料--- 88 | elasPlasticMaterial=steelDamperModel.Material(name="elasPlasticMaterial")#弹塑性材料名称定义 89 | elasPlasticMaterial.Elastic(table=((E,0.3),))#弹塑性材料弹性部分定义 90 | stressStrainTable=((fy,0),(fu,epsilon),(fu+1,1))#塑性应力应变关系表格 91 | elasPlasticMaterial.Plastic(table=stressStrainTable)#弹塑性材料塑性部分定义 92 | ######################################################################### 93 | ###########################---创建截面---################################## 94 | ###---三角钢板弹塑性截面--- 95 | bendPlateSection=steelDamperModel.HomogeneousShellSection(name="bendPlateSection", 96 | material="elasPlasticMaterial",thickness=shellThinkness)#建立各向同性壳截面 97 | ###---连接杆弹性截面--- 98 | solidSection=steelDamperModel.HomogeneousSolidSection(name='solidSection', material='elasticMaterial') 99 | ######################################################################### 100 | ###########################---截面指定---################################## 101 | ###---三角钢板截面指定--- 102 | trianglePart= steelDamperModel.parts['trianglePlatePart_1'] 103 | bendPlateFace=(trianglePart.faces,)#选取三角板所有的面 104 | trianglePart.SectionAssignment(region=bendPlateFace, sectionName='bendPlateSection')#截面指定 105 | ###---连接杆截面指定--- 106 | rod_region=(connectingRodPart.cells,) 107 | connectingRodPart.SectionAssignment(region=rod_region, sectionName='solidSection')#连接杆截面指定 108 | ###---滑槽截面指定--- 109 | slot_region=(slotPart.cells,) 110 | slotPart.SectionAssignment(region=slot_region, sectionName='solidSection')#滑槽截面指定 111 | ######################################################################### 112 | ###########################---装配件---################################### 113 | ###---三角钢板装配件--- 114 | rootAssembly=steelDamperModel.rootAssembly#根装配件 115 | #生成三角形钢板装配件实例 116 | trianglePlateInstance_1=rootAssembly.Instance(name="trianglePlateInstance_1",part=trianglePlatePart_1,dependent=ON) 117 | #生成连接杆装配件实例 118 | connectingRod_instance=rootAssembly.Instance(name="connectingRod_instance",part=connectingRodPart,dependent=ON) 119 | #连接杆与钢板装配实例 120 | ###移动连接杆到钢板顶部 121 | fixedPoint=trianglePlateInstance_1.vertices[0] 122 | movablePoint=connectingRod_instance.InterestingPoint(edge=connectingRod_instance.edges[0], rule=MIDDLE) 123 | rootAssembly.CoincidentPoint(fixedPoint=fixedPoint, movablePoint=movablePoint) 124 | ###转动连接杆 125 | rootAssembly.rotate(instanceList=('connectingRod_instance', ), 126 | axisPoint=((trianglePlateBottomWidth-trianglePlateTopWidth)*0.5,0,0.0), axisDirection=(0.0,1, 0.0), angle=90.0) 127 | ###沿X轴平行移动连接杆 128 | connectingRod_instance.ConvertConstraints()#将连接杆实例转换为绝对位置 129 | rootAssembly.translate(instanceList=('connectingRod_instance', ), vector=(trianglePlateTopWidth, 0.0,0.0)) 130 | ####对连接杆与钢板进行布尔并运算 131 | trianglePlateRod_instance=rootAssembly.InstanceFromBooleanMerge(name='trianglePlateRod_instance', instances=(trianglePlateInstance_1, 132 | connectingRod_instance,),keepIntersections=OFF, originalInstances=SUPPRESS,domain=GEOMETRY) 133 | ###滑槽装配件实例 134 | slot_instance=rootAssembly.Instance(name="slot_instance",part=slotPart,dependent=ON) 135 | fixedPoint=trianglePlateRod_instance.vertices[2] 136 | movablePoint=slot_instance.InterestingPoint(edge=slot_instance.edges[2],rule=MIDDLE) 137 | rootAssembly.CoincidentPoint(fixedPoint=fixedPoint,movablePoint=movablePoint) 138 | rootAssembly.rotate(instanceList=('slot_instance',),axisPoint=(0,0,0),axisDirection=(0,1,0),angle=90) 139 | slot_instance.ConvertConstraints() 140 | rootAssembly.translate(instanceList=('slot_instance',),vector=((trianglePlateBottomWidth-slotDepth)*0.5,0,0)) 141 | rootAssembly.translate(instanceList=('slot_instance',),vector=(0,trianglePlateHeight+2*rodRaidus+slotThickness+5,0)) 142 | ######################################################################### 143 | ###########################---荷载步设置---################################ 144 | ####---创建荷载步--- 145 | steelDamperModel.StaticStep(name='pushOver_1', previous='Initial', initialInc=maxInc, maxInc=maxInc, nlgeom=ON) 146 | for i1 in range(numStep-1): 147 | previousName = "pushOver_" + str(i1 + 1) 148 | currentName = "pushOver_" + str(i1 + 2) 149 | steelDamperModel.StaticStep(name=currentName,previous=previousName, initialInc=maxInc, maxInc=maxInc,nlgeom=ON) 150 | ######################################################################### 151 | ###########################---场变量输出设置---############################# 152 | #场变量输入名称修改 153 | steelDamperModel.fieldOutputRequests.changeKey(fromName='F-Output-1',toName='Selected Field Outputs') 154 | ######################################################################### 155 | ###########################---耦合设置---################################## 156 | ###---参考点与顶部线耦合设置--- 157 | refPointCoord=(trianglePlateBottomWidth*0.5,trianglePlateHeight+2*rodRaidus+5+slotThickness,0)#参考点坐标 158 | refPointid=rootAssembly.ReferencePoint(refPointCoord).id#建立参考点 159 | #建立参考点集合 160 | refPointRegion=rootAssembly.Set(referencePoints=(rootAssembly.referencePoints[refPointid],), name='refPointSet') 161 | slotUpFace = slot_instance.faces.findAt((refPointCoord,),)#通过边上一点选择边 162 | region_slotUpFace=regionToolset.Region(faces=slotUpFace)#集合域 163 | steelDamperModel.Coupling(name='coupling_refAndTopFace',controlPoint=refPointRegion,surface=region_slotUpFace, 164 | couplingType=KINEMATIC,influenceRadius=WHOLE_SURFACE)#建立控制点与边之间分布耦合 165 | #接触面设置 166 | leftSlotNode=(trianglePlateBottomWidth*0.5,trianglePlateHeight,rodRaidus) 167 | leftSlotSurface=slot_instance.faces.findAt((leftSlotNode,))#通过面上一点选取面 168 | rootAssembly.Surface(side1Faces=leftSlotSurface,name="leftSlotSurfaceInstance") 169 | region_leftSlotSurface=rootAssembly.surfaces['leftSlotSurfaceInstance'] 170 | #################### 171 | rightSlotNode=(trianglePlateBottomWidth*0.5,trianglePlateHeight,-rodRaidus) 172 | rightSlotSurface=slot_instance.faces.findAt((rightSlotNode,))#通过面上一点选取面 173 | rootAssembly.Surface(side1Faces=rightSlotSurface,name="rightSlotSurfaceInstance") 174 | region_rightSlotSurface=rootAssembly.surfaces['rightSlotSurfaceInstance'] 175 | #################### 176 | rodSurfaceNode=(trianglePlateBottomWidth*0.5,trianglePlateHeight+2*rodRaidus,0) 177 | rodSurface=trianglePlateRod_instance.faces.findAt((rodSurfaceNode,)) 178 | rootAssembly.Surface(side1Faces=rodSurface,name="rodSurfaceInstance") 179 | region_rodSurface=rootAssembly.surfaces['rodSurfaceInstance'] 180 | # ###法向耦合约束设置 181 | frictionless_interaction=steelDamperModel.ContactProperty('Frictionless') 182 | frictionless_interaction.TangentialBehavior(formulation=FRICTIONLESS) 183 | steelDamperModel.SurfaceToSurfaceContactStd(name='leftNormalInter',createStepName='Initial', master=region_leftSlotSurface, 184 | slave=region_rodSurface, sliding=FINITE, interactionProperty='Frictionless') 185 | steelDamperModel.SurfaceToSurfaceContactStd(name='rightNormalInter',createStepName='Initial', master=region_rightSlotSurface, 186 | slave=region_rodSurface, sliding=FINITE, interactionProperty='Frictionless') 187 | ######################################################################### 188 | ###########################---边界条件设置---############################## 189 | ###---约束边界条件--- 190 | bottomPointCoord=(trianglePlateBottomWidth*0.5,0,0)#底边上一点 191 | plateBottomEdge = trianglePlateRod_instance.edges.findAt((bottomPointCoord,),)#通过边上一点选择边 192 | region_bottomEdge=regionToolset.Region(edges=plateBottomEdge)#集合域 193 | steelDamperModel.DisplacementBC(name='initBC', createStepName='Initial',region=region_bottomEdge, 194 | u1=SET, u2=SET, u3=SET, ur1=SET,ur2=SET, ur3=SET)#底边固接 195 | steelDamperModel.DisplacementBC(name='refPointConstraint', createStepName='Initial',region=refPointRegion, 196 | u1=SET,u2=SET,u3=UNSET,ur1=SET,ur2=SET,ur3=SET) 197 | ######################################################################### 198 | ###########################---PushOver荷载设置---########################## 199 | region_pushOver = rootAssembly.sets['refPointSet']#参考点集 200 | # 沿整体坐标系Z做加载100mm,创建pushover位移荷载 201 | steelDamperModel.DisplacementBC(name='pushover', createStepName='pushOver_1', region=region_pushOver, u3=stepDisp) 202 | for i2 in range(numStep-1): 203 | stepName = "pushOver_" + str(i2 + 2) 204 | u3 = (i2 + 2) * stepDisp * (-1) ** (i2 + 1) 205 | steelDamperModel.boundaryConditions['pushover'].setValuesInStep(stepName=stepName, u3=u3)#随后荷载步修改 206 | ######################################################################### 207 | ###########################---网格划分---################################## 208 | ###---钢板部件网格划分--- 209 | meshPart=steelDamperModel.parts['trianglePlateRod_instance']#选取需要划分网格的部件(对部件进行网格划分) 210 | plate_findNode1=(0,0,0) 211 | plate_findNode2=(trianglePlateBottomWidth*0.5+1.5*trianglePlateTopWidth,trianglePlateHeight,0)#两对角点需求四条线 212 | plateEdges=trianglePlateRod_instance.edges.findAt((plate_findNode1,),(plate_findNode2,)) 213 | meshPart.seedEdgeBySize(edges=plateEdges,size=PlateSeedSize)#指定钢板划分网格最大尺寸mm 214 | plateFaces_findNode=(0,0,0) 215 | plateFace=trianglePlateRod_instance.faces.findAt((plateFaces_findNode,),) 216 | plateFaceRegion=(plateFace,) 217 | eleType1=mesh.ElemType(elemCode=S4R)#单元类型设置 218 | eleType2=mesh.ElemType(elemCode=S3)#单元类型设置 219 | meshPart.setElementType(regions=plateFaceRegion, elemTypes=(eleType1, eleType2))#单元类型指定 220 | ###---连接杆网格划分--- 221 | rod_findNode=(trianglePlateBottomWidth*0.5,trianglePlateHeight,0) 222 | rodCells=trianglePlateRod_instance.cells.findAt((rod_findNode,),) 223 | rodCellRegion=(rodCells,) 224 | rodEdge_findNode1=((trianglePlateBottomWidth-trianglePlateTopWidth)*0.5,trianglePlateHeight,0) 225 | rodEdge_findNode2=(0.5*trianglePlateBottomWidth+1.5*trianglePlateTopWidth,trianglePlateHeight,0) 226 | rodEdges=trianglePlateRod_instance.edges.findAt((rodEdge_findNode1,),(rodEdge_findNode2,)) 227 | meshPart.seedEdgeBySize(edges=rodEdges,size=RodSeedSize)#指定连接杆网格最大尺寸mm 228 | elemType1 = mesh.ElemType(elemCode=C3D8I) 229 | elemType2 = mesh.ElemType(elemCode=C3D6) 230 | elemType3 = mesh.ElemType(elemCode=C3D4) 231 | meshPart.setElementType(regions=rodCellRegion, elemTypes=(eleType1, eleType2,elemType3))#单元类型指定 232 | meshPart.generateMesh()#生成装配件实例网格 233 | ###---滑槽网格划分--- 234 | meshPart_slot=steelDamperModel.parts['slotPart']#选取需要划分网格的部件(对部件进行网格划分) 235 | slot_findNode=(trianglePlateBottomWidth*0.5,trianglePlateHeight+2*rodRaidus+slotThickness,0) 236 | slotCells=slot_instance.cells.findAt((slot_findNode,),) 237 | slotCellRegion=(slotCells,) 238 | slotEdges=slot_instance.edges 239 | meshPart_slot.seedEdgeBySize(edges=slotEdges,size=RodSeedSize)#指定连接杆网格最大尺寸mm 240 | elemType1 = mesh.ElemType(elemCode=C3D8I) 241 | elemType2 = mesh.ElemType(elemCode=C3D6) 242 | elemType3 = mesh.ElemType(elemCode=C3D4) 243 | meshPart_slot.setElementType(regions=slotCellRegion, elemTypes=(eleType1, eleType2,elemType3))#单元类型指定 244 | meshPart_slot.generateMesh()#生成装配件实例网格 245 | ######################################################################### 246 | ###########################---任务设置---################################## 247 | # mdb.Job(name='Job-pushOver', model='selfCenteringSteelDamper',multiprocessingMode=DEFAULT, 248 | # numCpus=12,numDomains=12, numGPUs=1)#任务参数设置 249 | # mdb.jobs['Job-pushOver'].submit(consistencyChecking=OFF)#提交任务 250 | 251 | 252 | 253 | ######################################################################### 254 | ######################################################################### 255 | 256 | 257 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /saveDataToSqlite.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @File : 234.py 3 | # @Date : 2020-09-02 18:14 4 | # @Email : {guojj@tongji.edu.cn/guojj01@gmail.com} 5 | # @Author : guojj 6 | 7 | 8 | ###导入必要的模块 9 | import records 10 | import numpy as np 11 | 12 | 13 | class SaveData(object): 14 | """将提取的数据存储到数据库中""" 15 | 16 | def __init__(self,dbPath): 17 | self._dbPath=dbPath 18 | 19 | @classmethod 20 | def initDB(self,dbPath): 21 | """初始化数据库""" 22 | self.db = records.Database('sqlite:///'+dbPath) 23 | tableNames=self.db.get_table_names() 24 | for each in tableNames: 25 | self.db.query("DROP TABLE IF EXISTS "+each) 26 | 27 | def saveNodes(self,nodes): 28 | """将节点列表存入数据库,[(tag1,x1,y1,z1),..]""" 29 | db=records.Database('sqlite:///'+self._dbPath) 30 | nodesDict=[{'tags':int(each[0]),'coords':str(each[1:])} for each in nodes] 31 | nodesTable=""" 32 | CREATE TABLE IF NOT EXISTS 33 | nodes( 34 | tags INT NOT NULL, 35 | coords MESSAGE_TEXT NOT NULL);""" 36 | db.query(nodesTable) 37 | insertNodes=""" 38 | INSERT INTO 39 | nodes(tags,coords) 40 | values (:tags,:coords) 41 | """ 42 | db.bulk_query(insertNodes,nodesDict) 43 | 44 | def saveElements(self,elements): 45 | """将单元列表存入数据库,[(tag1,n1,n2,..),..]""" 46 | db=records.Database('sqlite:///'+self._dbPath) 47 | elesDict=[{'tags':int(each[0]),'connectivity':str(each[1:])} for each in elements] 48 | elesTable=""" 49 | CREATE TABLE IF NOT EXISTS 50 | elements( 51 | tags INT NOT NULL, 52 | connectivity MESSAGE_TEXT NOT NULL);""" 53 | db.query(elesTable) 54 | insertEles=""" 55 | INSERT INTO 56 | elements(tags,connectivity) 57 | values (:tags,:connectivity) 58 | """ 59 | db.bulk_query(insertEles,elesDict) 60 | 61 | def getNode(self,tags): 62 | """返回特定节点的坐标""" 63 | db=records.Database('sqlite:///'+self._dbPath) 64 | conn = db.get_connection() 65 | try: 66 | queryValue=conn.query('select * from nodes where tags=='+str(tags)+';') 67 | returnValue=queryValue.all(as_dict=True)[0]['coords'] 68 | return returnValue 69 | except : 70 | print("Please enter correct node tag (integer)!") 71 | return 72 | 73 | def getAllNode(self): 74 | """返回所有节点坐标""" 75 | db=records.Database('sqlite:///'+self._dbPath) 76 | conn = db.get_connection() 77 | try: 78 | queryValue=conn.query('select * from nodes;') 79 | returnValue=queryValue.all(as_dict=True) 80 | return returnValue 81 | except : 82 | print("table nodes doesn't exitst!") 83 | return 84 | 85 | def getEle(self,tags): 86 | """返回特定节点的坐标""" 87 | db=records.Database('sqlite:///'+self._dbPath) 88 | conn = db.get_connection() 89 | try: 90 | queryValue=conn.query('select * from elements where tags=='+str(tags)+';') 91 | returnValue=queryValue.all(as_dict=True)[0]['connectivity'] 92 | return returnValue 93 | except : 94 | print("Please enter correct element tag (integer)!") 95 | return 96 | 97 | def getAllEle(self): 98 | """返回所有单元信息""" 99 | db=records.Database('sqlite:///'+self._dbPath) 100 | conn = db.get_connection() 101 | try: 102 | queryValue=conn.query('select * from elements;') 103 | returnValue=queryValue.all(as_dict=True) 104 | return returnValue 105 | except : 106 | print("table elements doesn't exitst!") 107 | return 108 | 109 | def saveMisesStress(self,mises): 110 | """将Mises应力列表存储到数据库""" 111 | db=records.Database('sqlite:///'+self._dbPath) 112 | elesDict=[{'eleTag':int(each[0]),'mises':str(each[1:])} for each in mises] 113 | 114 | elesTable=""" 115 | CREATE TABLE IF NOT EXISTS 116 | mises( 117 | eleTag INT NOT NULL, 118 | mises MESSAGE_TEXT NOT NULL);""" 119 | db.query(elesTable) 120 | insertEles=""" 121 | INSERT INTO 122 | mises(eleTag,mises) 123 | values (:eleTag,:mises) 124 | """ 125 | db.bulk_query(insertEles,elesDict) 126 | 127 | def getEleMises(self,eletags): 128 | """返回特定单元的Mises应力""" 129 | db=records.Database('sqlite:///'+self._dbPath) 130 | conn = db.get_connection() 131 | try: 132 | queryValue=conn.query('select * from mises where eleTag=='+str(eletags)+';') 133 | returnValue=queryValue.all(as_dict=True)[0]['mises'] 134 | return returnValue 135 | except : 136 | print("Please enter correct element tag (integer)!") 137 | return 138 | 139 | def getAllMises(self): 140 | """返回所有单元的Mises应力""" 141 | db = records.Database('sqlite:///' + self._dbPath) 142 | conn = db.get_connection() 143 | try: 144 | queryValue = conn.query('select * from mises;') 145 | returnValue = queryValue.all(as_dict=True) 146 | return returnValue 147 | except: 148 | print("table mises doesn't exitst!") 149 | return 150 | 151 | def savePEEQ(self,PEEQ): 152 | """将等效塑性应变列表存储到数据库""" 153 | db=records.Database('sqlite:///'+self._dbPath) 154 | elesDict=[{'eleTag':int(each[0]),'PEEQ':str(each[1:])} for each in PEEQ] 155 | 156 | elesTable=""" 157 | CREATE TABLE IF NOT EXISTS 158 | peeq( 159 | eleTag INT NOT NULL, 160 | PEEQ MESSAGE_TEXT NOT NULL);""" 161 | db.query(elesTable) 162 | insertEles=""" 163 | INSERT INTO 164 | peeq(eleTag,PEEQ) 165 | values (:eleTag,:PEEQ) 166 | """ 167 | db.bulk_query(insertEles,elesDict) 168 | 169 | def getAllPEEQ(self): 170 | """返回所有单元的等效塑性应变""" 171 | db = records.Database('sqlite:///' + self._dbPath) 172 | conn = db.get_connection() 173 | try: 174 | queryValue = conn.query('select * from peeq;') 175 | returnValue = queryValue.all(as_dict=True) 176 | return returnValue 177 | except: 178 | print("table peeq doesn't exitst!") 179 | return 180 | 181 | def saveNodeDisp(self,dispX,dispY,dispZ): 182 | """保存节点位移""" 183 | db=records.Database('sqlite:///'+self._dbPath) 184 | nodeDispDict=[{'nodeTag':int(x[0]),'dispX':str(x[1:]),'dispY':str(y[1:]),'dispZ':str(z[1:])} 185 | for x,y,z in zip(dispX,dispY,dispZ)] 186 | nodeDispTable=""" 187 | CREATE TABLE IF NOT EXISTS 188 | nodeDisp( 189 | nodeTag INT NOT NULL, 190 | dispX MESSAGE_TEXT NOT NULL, 191 | dispY MESSAGE_TEXT NOT NULL, 192 | dispZ MESSAGE_TEXT NOT NULL);""" 193 | db.query(nodeDispTable) 194 | insertEles=""" 195 | INSERT INTO 196 | nodeDisp(nodeTag,dispX,dispY,dispZ) 197 | values (:nodeTag,:dispX,:dispY,:dispZ) 198 | """ 199 | db.bulk_query(insertEles,nodeDispDict) 200 | 201 | def getnodeDisp(self,nodeTag): 202 | """返回特定节点位移""" 203 | db=records.Database('sqlite:///'+self._dbPath) 204 | conn = db.get_connection() 205 | try: 206 | queryValue=conn.query('select * from nodeDisp where nodeTag=='+str(nodeTag)+';') 207 | returnValueX=queryValue.all(as_dict=True)[0]['dispX'] 208 | returnValueY = queryValue.all(as_dict=True)[0]['dispY'] 209 | returnValueZ = queryValue.all(as_dict=True)[0]['dispZ'] 210 | return returnValueX,returnValueY,returnValueZ 211 | except : 212 | print("Please enter correct node tag (integer)!") 213 | return 214 | 215 | def getAllDisp(self): 216 | """返回所有节点位移""" 217 | db = records.Database('sqlite:///' + self._dbPath) 218 | conn = db.get_connection() 219 | try: 220 | queryValue = conn.query('select * from nodeDisp;') 221 | returnValue = queryValue.all(as_dict=True) 222 | return returnValue 223 | except: 224 | print("table nodeDisp doesn't exitst!") 225 | return 226 | 227 | def saveDispForce(self,refDisp,refLoad): 228 | """保存加载点力与位移时程""" 229 | db=records.Database('sqlite:///'+self._dbPath) 230 | loadForceDict=[{'refDisp':str(x),'refLoad':str(y)} 231 | for x,y in zip(refDisp,refLoad)] 232 | dispForceTable=""" 233 | CREATE TABLE IF NOT EXISTS 234 | dispForce( 235 | refDisp MESSAGE_TEXT NOT NULL, 236 | refLoad MESSAGE_TEXT NOT NULL);""" 237 | db.query(dispForceTable) 238 | insertEles=""" 239 | INSERT INTO 240 | dispForce(refDisp,refLoad) 241 | values (:refDisp,:refLoad) 242 | """ 243 | db.bulk_query(insertEles,loadForceDict) 244 | 245 | def getRefResponse(self): 246 | """返回加载点力与位移时程""" 247 | db = records.Database('sqlite:///' + self._dbPath) 248 | conn = db.get_connection() 249 | try: 250 | queryValue = conn.query('select * from dispForce;') 251 | returnValue = queryValue.all(as_dict=True) 252 | return returnValue 253 | except: 254 | print("table dispForce doesn't exitst!") 255 | return 256 | 257 | 258 | 259 | ################################################################################ 260 | if __name__ == '__main__': 261 | dbPath="postResultDB.db" 262 | SaveData.initDB(dbPath) 263 | saveInstance=SaveData(dbPath) 264 | nodes=np.loadtxt("postResults/nodes.txt") 265 | saveInstance.saveNodes(nodes) 266 | elements=np.loadtxt("postResults/elements.txt") 267 | saveInstance.saveElements(elements) 268 | mises=np.loadtxt("postResults/misesStress.txt") 269 | saveInstance.saveMisesStress(mises) 270 | PEEQ=np.loadtxt("postResults/PEEQ.txt") 271 | saveInstance.savePEEQ(PEEQ) 272 | dispX=np.loadtxt("postResults/dispX.txt") 273 | dispY= np.loadtxt("postResults/dispY.txt") 274 | dispZ = np.loadtxt("postResults/dispZ.txt") 275 | saveInstance.saveNodeDisp(dispX,dispY,dispZ) 276 | refDisp = np.loadtxt("postResults/refDisp.txt") 277 | refLoad = np.loadtxt("postResults/refLoad.txt") 278 | saveInstance.saveDispForce(refDisp,refLoad) 279 | 280 | 281 | 282 | 283 | --------------------------------------------------------------------------------