Disabled external gits
No files matched your search
@@ -0,0 +1,834 @@
|
||||
v 3.06161699786838e-17 -7.49879891330929e-33 0.5
|
||||
v 3.06161699786838e-17 -7.49879891330929e-33 -0.5
|
||||
v 0.154508497187474 -3.78436673043416e-17 -0.475528258147577
|
||||
v 0.293892626146237 -7.19829327805997e-17 -0.404508497187474
|
||||
v 0.404508497187474 -9.90760072617093e-17 -0.293892626146236
|
||||
v 0.475528258147577 -1.16470831848909e-16 -0.154508497187473
|
||||
v 0.5 -1.22464679914735e-16 7.6571373978539e-16
|
||||
v 0.475528258147577 -1.16470831848909e-16 0.154508497187474
|
||||
v 0.404508497187474 -9.90760072617092e-17 0.293892626146237
|
||||
v 0.293892626146237 -7.19829327805998e-17 0.404508497187473
|
||||
v 0.154508497187475 -3.78436673043417e-17 0.475528258147576
|
||||
v 0.21857645514496 0.136716465258129 0.428407447861946
|
||||
v 0.475945187701446 -0.132880263668928 0.0762824608354488
|
||||
v 0.218576349120797 -0.134908613951094 -0.428980239040003
|
||||
v 0.228603425820446 -0.140038091834834 0.422054269660211
|
||||
v 0.437104447096958 0.151793486569612 0.189468835862535
|
||||
v 0.42898023903994 0.134908613950884 -0.21857634912105
|
||||
v 0.428980239039898 -0.134908613951062 -0.218576349121023
|
||||
v 0.218576349121032 0.134908613951053 -0.428980239039896
|
||||
v 0.340440645253916 0.134908613951044 0.34044064525392
|
||||
v 0.476615030125843 -0.131924241455095 -0.0737163996315581
|
||||
v 0.407622547196207 -0.259520994885 -0.128423955051913
|
||||
v 0.338436818269637 -0.252043139096244 -0.26820659215246
|
||||
v 0.340989631871085 -0.116746524471516 -0.34654915954341
|
||||
v 0.075316277025205 -0.134908613951047 0.475528258147578
|
||||
v 0.0753162770252058 0.134908613951052 -0.475528258147577
|
||||
v 0.337051887252752 0.13152434625125 -0.345104870499591
|
||||
v 0.342307229899869 0.259749321291958 -0.255648294433281
|
||||
v 0.235302886190634 0.257758938760451 0.358040334654413
|
||||
v 0.0930553185121102 0.241091096498632 0.428037137273972
|
||||
v 0.414887348894352 0.253233345682864 -0.117223548665273
|
||||
v 0.309219636002729 0.365205559163796 -0.144941768535501
|
||||
v 0.116382730487621 0.357335962703667 0.329797013029059
|
||||
v 0.220295554503833 0.356044147287606 -0.273317459830304
|
||||
v 0.173924737961772 0.443407381211481 -0.152118637293744
|
||||
v 0.0757439138278267 0.415836842579461 -0.2671003179923
|
||||
v 0.0224933467184133 0.480041055177656 -0.138038526134294
|
||||
v 0.248065266401332 0.358015947011543 0.245536566096914
|
||||
v 0.138163331821839 0.43047956133561 0.21353744639334
|
||||
v 0.360552014587397 0.346405942121308 -0.00227333235984791
|
||||
v 0.123093945281709 0.484207258358844 -0.0197790694319915
|
||||
v -0.0375624502146155 0.498585389330104 0.0012930121510933
|
||||
v -0.0319756224028659 0.329253812136088 0.374925975048146
|
||||
v -0.0571707300985015 0.188277472409031 0.459655415505214
|
||||
v 0.44634465869394 0.222444950782125 0.0359817943817138
|
||||
v 0.114071738612042 0.30750614917439 -0.377395822274126
|
||||
v 0.236387555749274 0.430565411758525 0.0934577427723124
|
||||
v 0.378115930351658 0.292151103254715 0.147227973161872
|
||||
v 0.0698331513994325 -0.131524346251195 -0.477309833660296
|
||||
v -0.0276507157238025 0.368077837732622 -0.337274581446689
|
||||
v -0.132019323454869 0.46789161623721 -0.116826083086996
|
||||
v -0.178527337205295 0.268217150323689 0.382344805303572
|
||||
v -0.195982573985885 0.117715178528912 0.444672876885665
|
||||
v -0.188769871137012 0.462097824846099 0.0288363663352296
|
||||
v -0.311118332326446 0.185953595932789 0.344422187801651
|
||||
v 0.298513275017753 -0.364576673892107 -0.167253321318123
|
||||
v -0.27446477920923 0.408828269442573 -0.0867671082739308
|
||||
v -0.321076581736832 0.0337877006396921 0.381796044958135
|
||||
v -0.406068994209582 0.0890512487956863 0.27780901178606
|
||||
v -0.396337226815336 -0.0658166787739775 0.297632268807486
|
||||
v 0.137344602759695 -0.267387515925555 0.399550217644719
|
||||
v -0.469353412437567 -0.00745235730436951 0.172197086513736
|
||||
v -0.438850244007533 -0.16046355744979 0.17793793880195
|
||||
v -0.488260481987745 -0.0978280168539874 0.0450708425427184
|
||||
v -0.433483128474169 -0.244453321072111 0.0483213321946162
|
||||
v -0.460620100758965 -0.173287974513347 -0.0883198769579221
|
||||
v -0.383511806626786 -0.309356779000242 -0.08495338406711
|
||||
v -0.336717499334961 -0.365993326701377 0.0516740791080927
|
||||
v -0.267862281691792 -0.414575366652434 -0.0798565176542698
|
||||
v -0.205085219904653 -0.452251021719178 0.0583872069088724
|
||||
v -0.389473197418456 -0.226083984285031 -0.217247924138414
|
||||
v -0.445256364809781 -0.0799966822341631 -0.212949055945092
|
||||
v -0.00351125947165275 -0.267035886479874 0.422704987418922
|
||||
v -0.353169743739217 -0.125114465368412 -0.331085340452809
|
||||
v -0.38892388844103 0.0261181792321889 -0.313139026174485
|
||||
v -0.278756909608118 -0.262391732725563 -0.321628922740179
|
||||
v -0.249429844449192 -0.39750217428021 0.172559480007787
|
||||
v -0.125203314206269 -0.478452051724907 -0.0735375027587528
|
||||
v -0.0528582364531956 -0.493487744300911 0.0606288138087549
|
||||
v 0.271731582933658 -0.249600298700644 0.337433901267964
|
||||
v -0.495847117939593 0.0542719818547096 0.034499095880349
|
||||
v 0.341636271151409 -0.364235836672196 -0.0248377438078891
|
||||
v -0.278221380393658 -0.0165162196036634 -0.415114535979952
|
||||
v -0.385894465893779 0.231366911979078 0.218070661102819
|
||||
v 0.129422773211733 -0.26368230955868 -0.404624993543385
|
||||
v 0.17079787798835 -0.360453290963367 0.301498772648173
|
||||
v -0.2972397651044 0.134475553784439 -0.378899521608367
|
||||
v -0.390729424978202 0.17308135749756 -0.259563788196669
|
||||
v 0.0302401087170613 -0.494617483324727 -0.0666264287973931
|
||||
v -0.0447104151313644 -0.455911463185833 -0.200363960118914
|
||||
v -0.289781305004565 -0.107480642258869 0.393032704503674
|
||||
v -0.28072748874216 0.276043192337753 -0.308208100199367
|
||||
v 0.106085899784673 -0.483055958177403 0.0735032185430484
|
||||
v -0.143288452953271 0.380504725979635 0.291006138693707
|
||||
v -0.0207720062787277 -0.262149359393134 -0.425260199319106
|
||||
v -0.0793282266177742 -0.112493174960849 0.480679017691543
|
||||
v -0.210229488803243 0.104747954203238 -0.441397131988602
|
||||
v 0.435024352571936 -0.127806035969131 0.210759174982314
|
||||
v 0.298839864283654 -0.34288662805342 0.207661974894498
|
||||
v -0.343961566185834 -0.213169748618088 0.293681969588004
|
||||
v -0.217656630917657 -0.259665634918282 0.367694641054313
|
||||
v -0.318981501523703 0.381763369474201 0.0500752574969736
|
||||
v -0.395445063483211 0.303503289973959 -0.0388452666581461
|
||||
v 0.00695685172784659 -0.466794760772503 0.179037017204205
|
||||
v -0.141786434074944 -0.0639250457860653 -0.475194902785753
|
||||
v 0.123376202006679 -0.445805073774975 -0.189831896621448
|
||||
v 0.0273264572598231 -0.36207385125428 -0.343737968475292
|
||||
v -0.179178868825853 0.231344360320625 -0.40543152308883
|
||||
v -0.131442519100517 -0.37228536331636 -0.30680037880178
|
||||
v 0.213344976802497 -0.44944368426887 -0.0498427080320272
|
||||
v -0.095411435088729 0.468568967697982 0.146081417588813
|
||||
v 0.19556911033449 -0.349389679263868 -0.299465482329545
|
||||
v -0.212579734450761 0.392914303643436 -0.22456225527287
|
||||
v 0.00442729082563762 0.431790532829453 0.252066131907487
|
||||
v 0.251435921428911 -0.424020659066107 0.0835850351458869
|
||||
v -0.0716881267417996 0.0362403081699758 0.493505271043782
|
||||
v 0.409702957808806 -0.250532734704164 0.139200701163351
|
||||
v 0.354048851093961 -0.123591021755264 0.33071841554491
|
||||
v -0.409329654955812 0.269763307055223 0.0983717019288848
|
||||
v -0.23775056881332 0.409432492346691 0.160747321096556
|
||||
v -0.280167779637764 0.310303261210272 0.274258821799984
|
||||
v 0.0390199999029228 -0.340176969429353 0.364358434892671
|
||||
v -0.106955495739533 -0.389774683020182 0.294340310538035
|
||||
v -0.125152025350624 -0.457070129870627 0.159448634144933
|
||||
v 0.250205349609497 0.430527105380925 -0.0452072401182732
|
||||
v -0.15862733630032 -0.0449406159687499 0.472035707563119
|
||||
v -0.372118237460504 -0.283526014116421 0.176468174662014
|
||||
v -0.235245742246689 -0.152187819676347 -0.41412354231191
|
||||
v 0.479986141812706 0.124680814448665 -0.063780860578784
|
||||
v -0.0761042573074939 0.431963531953512 -0.240032600039915
|
||||
v -0.288453021308633 -0.353652776154199 -0.204265925734934
|
||||
v -0.458840137015611 0.057463941494015 -0.190167358112447
|
||||
v -0.444083105517519 0.194920415588484 -0.121639742603844
|
||||
v -0.178055249060845 -0.43316536366806 -0.175111667230364
|
||||
v -0.491963173165518 -0.0298523928793253 -0.0841490991531884
|
||||
v -0.45636138284715 0.138396610027018 0.150268648023688
|
||||
v -0.345904715972311 0.313415014736247 -0.179223201639723
|
||||
v -0.153169726530236 -0.269052072762942 -0.392619430258638
|
||||
v -0.0419923946510265 0.170189522618945 -0.468265058681734
|
||||
v 0.243612070418092 0.241981955824921 -0.363452737232445
|
||||
v 0.338867576345089 0.252678472264692 0.2670624559087
|
||||
v 0.426863022631355 -0.25994025908482 0.0147993789376581
|
||||
v 0.158342102182598 -0.434609327079221 0.18984865417522
|
||||
v 0.0452931243905481 0.0952764475019849 0.488744239285072
|
||||
v -0.237259629761916 0.0166159415076913 0.439808797744033
|
||||
v 0.247175666187241 -0.238473344419651 -0.363365730423495
|
||||
v 0.0577997827759178 0.48434516267528 0.10985876616872
|
||||
v -0.334770924239934 0.332574086299653 0.165296416795679
|
||||
v -0.153183582101622 0.339412359720881 -0.333667559470828
|
||||
v 0.36785960116632 -0.228792320684729 0.249666553277471
|
||||
v 0.483390586525237 0.102332156736947 0.0765615475049495
|
||||
v 0.139648641361451 0.213951152339616 -0.429794324507027
|
||||
v -0.0358864034291634 0.302032201639968 -0.396848478920397
|
||||
v -0.180786711862885 -0.175443810495746 0.431897712627121
|
||||
v 0.348215026659532 -0.346723777603642 0.0923521372398145
|
||||
v -0.114480413553308 -0.290654614949134 0.390402522688358
|
||||
v -0.272442803422386 -0.321472772094441 0.269128548588341
|
||||
v -0.466114498296331 0.180818120755528 0.00648703972541844
|
||||
v -0.129415184584831 -0.203585571998795 -0.437955048918034
|
||||
v 0.0643376427947934 -0.412575814735467 0.275030661590622
|
||||
v -0.485934856252322 0.0906364933467189 -0.0751820560562512
|
||||
v -2.77555756156289e-16 3.19189119579733e-16 -1.2490009027033e-16
|
||||
v -0.251828742757562 0.0139490906784806 -0.0181338406388946
|
||||
v 0.197996662720562 -0.0791211777945037 0.136432807235424
|
||||
v 0.125255777218953 0.210831018463626 -0.063969097850248
|
||||
v -0.139628236563409 -0.21265335644906 0.00545121255949739
|
||||
v -0.145223690886062 0.189924594351579 0.11159305462841
|
||||
v -0.112897563504534 -0.0373976158431084 -0.223966661594476
|
||||
v 0.225528258147577 -0.0232431701377701 -0.114912387106339
|
||||
v -0.118530098445147 -0.0689806932344922 0.2117841676383
|
||||
v 0.098269738040353 0.147959392484917 0.178021817259433
|
||||
v 0.100852235573853 -0.219450649709681 -0.0387973024559412
|
||||
v -0.100480207820675 0.192284757140571 -0.148991345058649
|
||||
v 0.08807336311451 0.0516996280513727 -0.271061939721184
|
||||
v 0.272113071694785 0.101244013250397 0.0512575837900759
|
||||
v 0.0341720627218518 -0.221571915156144 0.170600381517002
|
||||
v 0.113793744063312 -0.150466918879953 -0.232830800332848
|
||||
v 0.068592399702004 -0.0245878691620408 0.288679790541826
|
||||
v -0.0741210186337665 0.111594614690448 0.278407708187608
|
||||
v -0.0351094203418499 0.30351870487887 -0.00261521319733849
|
||||
v -0.258447343925187 0.0495111872633636 0.167086499211952
|
||||
v -0.271439309774019 -0.125349807194904 0.104052998028547
|
||||
v -0.0485204373172835 -0.250891695571267 -0.169649174254392
|
||||
v -0.245408905954284 -0.137064807392418 -0.132337064396614
|
||||
v -0.247561324014027 0.19563057757812 -0.0400712992459122
|
||||
v -0.245489451032576 0.0855397985783712 -0.187709278356085
|
||||
v 0.27254656245515 -0.16399276001755 -0.00766125806031415
|
||||
v 0.273716986928946 0.149504817170547 -0.136480234333616
|
||||
v 0.0525334922800396 0.245214764318482 -0.222591039627852
|
||||
v -0.025453222260026 0.265072731295802 0.212780231418037
|
||||
v 0.10188342337719 0.303246953287615 0.102540160700209
|
||||
v -0.14157478784597 -0.241776139413833 0.180194715613577
|
||||
v -0.0121617817639016 -0.325829668630181 0.0394634260162139
|
||||
v 0.222619980200421 0.0438990087026778 0.254181668630204
|
||||
v 0.187862004819913 -0.26556009247797 0.101876795667186
|
||||
v 0.342239361396159 -0.0424148965243595 0.0738730045314498
|
||||
v -0.120466338945889 0.114580505991094 -0.297963959751455
|
||||
v 0.15154406307463 -0.163641254596307 0.268108582070898
|
||||
f 166 170 163 182
|
||||
f 165 162 171 180
|
||||
f 167 171 162 180
|
||||
f 4 5 27 169
|
||||
f 163 166 162 170
|
||||
f 4 24 169 177
|
||||
f 167 173 163 185
|
||||
f 162 163 167 173
|
||||
f 158 136 181 185
|
||||
f 162 171 170 178
|
||||
f 162 163 170 181
|
||||
f 162 167 163 181
|
||||
f 4 169 27 174
|
||||
f 170 171 162 179
|
||||
f 162 173 165 174
|
||||
f 170 178 171 179
|
||||
f 158 181 163 185
|
||||
f 162 176 164 178
|
||||
f 162 170 167 181
|
||||
f 162 170 176 178
|
||||
f 162 166 163 184
|
||||
f 167 170 162 179
|
||||
f 129 169 6 196
|
||||
f 162 165 169 174
|
||||
f 73 176 170 178
|
||||
f 119 181 136 185
|
||||
f 4 169 174 177
|
||||
f 72 132 135 163
|
||||
f 27 174 169 188
|
||||
f 158 119 136 185
|
||||
f 64 66 163 182
|
||||
f 167 162 171 179
|
||||
f 66 135 64 163
|
||||
f 7 129 6 196
|
||||
f 162 173 167 180
|
||||
f 95 177 168 183
|
||||
f 162 177 172 183
|
||||
f 4 24 5 169
|
||||
f 27 169 5 188
|
||||
f 162 169 165 175
|
||||
f 162 164 169 175
|
||||
f 129 175 169 196
|
||||
f 168 177 162 183
|
||||
f 132 161 135 163
|
||||
f 119 148 84 167
|
||||
f 162 165 173 180
|
||||
f 164 162 171 175
|
||||
f 165 171 162 175
|
||||
f 158 81 161 163
|
||||
f 30 171 178 179
|
||||
f 64 81 62 163
|
||||
f 169 162 174 177
|
||||
f 66 163 182 184
|
||||
f 169 177 23 187
|
||||
f 162 170 166 176
|
||||
f 54 167 102 185
|
||||
f 68 166 67 182
|
||||
f 162 168 163 173
|
||||
f 164 171 162 178
|
||||
f 161 158 163 185
|
||||
f 65 68 67 182
|
||||
f 166 168 162 183
|
||||
f 129 6 169 188
|
||||
f 162 163 168 184
|
||||
f 165 175 40 191
|
||||
f 129 169 175 188
|
||||
f 119 167 84 181
|
||||
f 62 64 163 182
|
||||
f 18 169 23 187
|
||||
f 67 182 166 184
|
||||
f 162 168 166 184
|
||||
f 168 174 162 177
|
||||
f 164 162 169 172
|
||||
f 167 181 119 185
|
||||
f 126 178 170 179
|
||||
f 72 163 135 184
|
||||
f 72 132 163 186
|
||||
f 54 180 167 185
|
||||
f 62 163 81 181
|
||||
f 162 168 173 174
|
||||
f 66 135 163 184
|
||||
f 165 174 173 189
|
||||
f 38 141 171 191
|
||||
f 140 174 188 189
|
||||
f 161 163 132 186
|
||||
f 24 23 18 169
|
||||
f 62 163 181 182
|
||||
f 65 182 67 184
|
||||
f 166 162 172 183
|
||||
f 140 174 27 188
|
||||
f 162 166 172 176
|
||||
f 4 14 24 177
|
||||
f 23 169 24 177
|
||||
f 169 172 162 177
|
||||
f 163 173 168 186
|
||||
f 60 181 170 182
|
||||
f 119 148 167 185
|
||||
f 57 173 51 180
|
||||
f 72 163 184 186
|
||||
f 41 35 165 180
|
||||
f 41 37 35 180
|
||||
f 141 171 48 175
|
||||
f 56 177 172 187
|
||||
f 135 161 81 163
|
||||
f 95 49 168 177
|
||||
f 102 54 120 167
|
||||
f 34 140 188 189
|
||||
f 176 178 73 198
|
||||
f 162 172 164 176
|
||||
f 141 171 175 194
|
||||
f 60 170 91 182
|
||||
f 130 37 180 189
|
||||
f 56 23 177 187
|
||||
f 22 18 23 187
|
||||
f 121 55 167 179
|
||||
f 6 169 21 196
|
||||
f 60 91 100 182
|
||||
f 12 30 171 178
|
||||
f 65 66 182 184
|
||||
f 91 170 100 182
|
||||
f 164 172 169 187
|
||||
f 116 178 126 179
|
||||
f 125 165 40 191
|
||||
f 69 67 166 184
|
||||
f 96 73 170 178
|
||||
f 113 51 57 173
|
||||
f 57 173 180 185
|
||||
f 136 119 84 181
|
||||
f 84 167 121 181
|
||||
f 83 75 74 186
|
||||
f 134 131 69 183
|
||||
f 167 179 55 181
|
||||
f 130 180 173 189
|
||||
f 145 179 170 181
|
||||
f 48 171 141 191
|
||||
f 48 175 171 191
|
||||
f 102 167 148 185
|
||||
f 64 135 81 163
|
||||
f 30 178 144 179
|
||||
f 57 180 54 185
|
||||
f 121 52 55 179
|
||||
f 40 175 165 188
|
||||
f 60 91 170 181
|
||||
f 130 51 173 180
|
||||
f 76 183 168 184
|
||||
f 74 75 72 184
|
||||
f 140 19 27 174
|
||||
f 165 180 171 191
|
||||
f 49 174 168 177
|
||||
f 83 74 168 186
|
||||
f 84 121 55 181
|
||||
f 69 70 78 166
|
||||
f 120 167 54 180
|
||||
f 121 167 55 181
|
||||
f 148 121 84 167
|
||||
f 74 128 168 184
|
||||
f 131 166 69 183
|
||||
f 156 170 176 192
|
||||
f 74 75 184 186
|
||||
f 67 68 69 166
|
||||
f 65 67 66 184
|
||||
f 117 164 150 196
|
||||
f 96 156 154 170
|
||||
f 98 150 164 196
|
||||
f 145 170 58 181
|
||||
f 161 133 158 185
|
||||
f 24 18 5 169
|
||||
f 78 183 166 193
|
||||
f 34 32 165 188
|
||||
f 98 117 150 196
|
||||
f 41 35 125 165
|
||||
f 35 34 32 165
|
||||
f 73 156 170 176
|
||||
f 74 184 168 186
|
||||
f 72 184 75 186
|
||||
f 133 161 132 186
|
||||
f 119 102 148 185
|
||||
f 150 164 117 195
|
||||
f 34 188 165 189
|
||||
f 57 54 102 185
|
||||
f 148 102 120 167
|
||||
f 170 181 163 182
|
||||
f 12 178 171 194
|
||||
f 6 18 21 169
|
||||
f 5 169 6 188
|
||||
f 136 62 81 181
|
||||
f 171 180 167 190
|
||||
f 58 170 91 181
|
||||
f 78 166 70 193
|
||||
f 2 168 49 174
|
||||
f 34 140 28 188
|
||||
f 40 125 32 165
|
||||
f 38 48 141 191
|
||||
f 169 174 165 188
|
||||
f 40 175 48 191
|
||||
f 113 130 51 173
|
||||
f 66 72 135 184
|
||||
f 169 187 21 196
|
||||
f 131 166 183 184
|
||||
f 74 128 83 168
|
||||
f 18 21 169 187
|
||||
f 7 6 21 196
|
||||
f 64 65 66 182
|
||||
f 69 166 131 184
|
||||
f 56 112 172 177
|
||||
f 76 168 128 184
|
||||
f 166 182 68 192
|
||||
f 159 95 168 183
|
||||
f 34 165 35 189
|
||||
f 96 170 126 178
|
||||
f 172 183 89 193
|
||||
f 150 118 98 164
|
||||
f 172 177 106 183
|
||||
f 168 183 166 184
|
||||
f 111 167 120 180
|
||||
f 17 5 6 188
|
||||
f 30 171 179 190
|
||||
f 130 37 51 180
|
||||
f 40 165 32 188
|
||||
f 100 182 170 192
|
||||
f 112 106 172 177
|
||||
f 74 76 128 184
|
||||
f 170 179 167 181
|
||||
f 32 125 35 165
|
||||
f 41 165 125 191
|
||||
f 113 173 57 185
|
||||
f 2 168 174 197
|
||||
f 18 6 5 169
|
||||
f 167 180 111 190
|
||||
f 126 170 145 179
|
||||
f 12 144 30 178
|
||||
f 91 126 154 170
|
||||
f 69 68 70 166
|
||||
f 4 27 19 174
|
||||
f 137 92 173 186
|
||||
f 25 73 178 198
|
||||
f 29 171 141 194
|
||||
f 60 58 91 181
|
||||
f 120 167 111 190
|
||||
f 111 120 54 180
|
||||
f 150 118 164 198
|
||||
f 30 33 29 171
|
||||
f 69 131 67 184
|
||||
f 95 49 159 168
|
||||
f 68 182 127 192
|
||||
f 117 187 164 196
|
||||
f 166 176 170 192
|
||||
f 33 171 30 190
|
||||
f 57 51 54 180
|
||||
f 137 92 113 173
|
||||
f 22 23 56 187
|
||||
f 37 36 35 189
|
||||
f 29 38 141 171
|
||||
f 150 164 195 198
|
||||
f 180 190 171 191
|
||||
f 145 91 58 170
|
||||
f 41 180 165 191
|
||||
f 82 187 172 195
|
||||
f 137 173 185 186
|
||||
f 113 137 173 185
|
||||
f 112 106 177 183
|
||||
f 164 187 117 195
|
||||
f 154 170 156 192
|
||||
f 148 120 121 167
|
||||
f 165 188 174 189
|
||||
f 76 138 168 183
|
||||
f 116 96 126 178
|
||||
f 76 138 128 168
|
||||
f 82 56 172 187
|
||||
f 172 176 166 193
|
||||
f 9 98 118 164
|
||||
f 30 29 12 171
|
||||
f 70 166 192 193
|
||||
f 33 38 29 171
|
||||
f 165 175 169 188
|
||||
f 96 73 156 170
|
||||
f 141 175 16 194
|
||||
f 96 25 73 178
|
||||
f 45 175 40 188
|
||||
f 98 164 9 196
|
||||
f 121 94 52 190
|
||||
f 106 56 112 172
|
||||
f 70 68 77 166
|
||||
f 70 192 124 193
|
||||
f 169 175 164 196
|
||||
f 31 45 40 188
|
||||
f 172 177 169 187
|
||||
f 106 89 172 183
|
||||
f 113 149 130 173
|
||||
f 149 189 173 197
|
||||
f 121 167 94 190
|
||||
f 171 175 165 191
|
||||
f 93 110 193 195
|
||||
f 172 193 110 195
|
||||
f 125 40 47 191
|
||||
f 3 49 14 177
|
||||
f 96 154 126 170
|
||||
f 78 90 183 193
|
||||
f 152 26 174 189
|
||||
f 113 57 137 185
|
||||
f 16 194 175 196
|
||||
f 60 62 181 182
|
||||
f 110 82 172 195
|
||||
f 92 149 113 173
|
||||
f 146 23 24 177
|
||||
f 34 28 32 188
|
||||
f 163 185 173 186
|
||||
f 72 75 132 186
|
||||
f 91 145 126 170
|
||||
f 38 171 33 191
|
||||
f 124 192 104 193
|
||||
f 18 22 21 187
|
||||
f 77 166 68 192
|
||||
f 130 36 37 189
|
||||
f 30 179 43 190
|
||||
f 131 183 76 184
|
||||
f 89 110 172 193
|
||||
f 121 120 94 167
|
||||
f 9 164 118 194
|
||||
f 173 174 168 197
|
||||
f 12 171 29 194
|
||||
f 56 23 112 177
|
||||
f 116 1 96 178
|
||||
f 17 27 5 188
|
||||
f 140 27 28 188
|
||||
f 104 192 176 193
|
||||
f 120 94 167 190
|
||||
f 112 177 107 183
|
||||
f 82 56 110 172
|
||||
f 169 164 187 196
|
||||
f 164 175 171 194
|
||||
f 118 194 164 198
|
||||
f 3 174 49 177
|
||||
f 9 164 194 196
|
||||
f 70 166 77 192
|
||||
f 167 180 173 185
|
||||
f 146 24 14 177
|
||||
f 30 44 43 179
|
||||
f 101 154 156 192
|
||||
f 152 174 140 189
|
||||
f 166 182 163 184
|
||||
f 92 149 173 197
|
||||
f 171 190 33 191
|
||||
f 60 63 62 182
|
||||
f 45 129 175 188
|
||||
f 163 181 167 185
|
||||
f 150 195 99 198
|
||||
f 167 179 171 190
|
||||
f 143 193 176 195
|
||||
f 164 176 172 195
|
||||
f 171 178 164 194
|
||||
f 164 178 176 198
|
||||
f 9 194 16 196
|
||||
f 129 17 6 188
|
||||
f 78 89 90 193
|
||||
f 10 118 15 194
|
||||
f 10 15 178 194
|
||||
f 150 99 80 198
|
||||
f 83 186 168 197
|
||||
f 111 190 180 191
|
||||
f 77 68 127 192
|
||||
f 127 68 65 182
|
||||
f 118 15 194 198
|
||||
f 10 15 11 178
|
||||
f 19 3 4 174
|
||||
f 9 16 8 196
|
||||
f 45 31 129 188
|
||||
f 30 144 44 179
|
||||
f 149 153 189 197
|
||||
f 40 32 31 188
|
||||
f 159 168 138 183
|
||||
f 124 123 104 192
|
||||
f 89 183 90 193
|
||||
f 104 176 143 193
|
||||
f 62 63 64 182
|
||||
f 137 185 133 186
|
||||
f 178 194 15 198
|
||||
f 47 40 48 191
|
||||
f 89 110 106 172
|
||||
f 75 83 87 186
|
||||
f 123 176 104 192
|
||||
f 105 49 2 168
|
||||
f 107 177 95 183
|
||||
f 87 186 83 197
|
||||
f 173 186 92 197
|
||||
f 73 122 176 198
|
||||
f 159 138 95 183
|
||||
f 149 153 50 189
|
||||
f 112 107 106 183
|
||||
f 137 133 88 186
|
||||
f 120 111 94 190
|
||||
f 110 56 106 172
|
||||
f 93 193 143 195
|
||||
f 170 182 166 192
|
||||
f 173 180 165 189
|
||||
f 10 178 11 194
|
||||
f 114 190 111 191
|
||||
f 52 53 55 179
|
||||
f 173 189 174 197
|
||||
f 139 174 26 189
|
||||
f 19 140 152 174
|
||||
f 116 145 53 179
|
||||
f 36 34 35 189
|
||||
f 100 127 182 192
|
||||
f 116 126 145 179
|
||||
f 134 78 90 183
|
||||
f 112 23 146 177
|
||||
f 89 93 110 193
|
||||
f 115 110 93 195
|
||||
f 63 60 100 182
|
||||
f 159 128 138 168
|
||||
f 11 144 12 178
|
||||
f 46 140 34 189
|
||||
f 168 184 163 186
|
||||
f 16 175 151 196
|
||||
f 106 90 89 183
|
||||
f 76 131 109 183
|
||||
f 41 42 37 180
|
||||
f 2 3 26 174
|
||||
f 143 176 86 195
|
||||
f 70 77 124 192
|
||||
f 137 88 92 186
|
||||
f 16 151 8 196
|
||||
f 73 122 156 176
|
||||
f 3 2 49 174
|
||||
f 150 80 118 198
|
||||
f 155 117 187 195
|
||||
f 160 143 104 176
|
||||
f 84 55 59 181
|
||||
f 25 61 73 198
|
||||
f 33 30 43 190
|
||||
f 166 183 172 193
|
||||
f 105 168 2 197
|
||||
f 107 85 95 177
|
||||
f 150 117 99 195
|
||||
f 79 78 70 193
|
||||
f 141 16 20 194
|
||||
f 16 141 48 175
|
||||
f 111 180 147 191
|
||||
f 45 129 151 175
|
||||
f 86 195 176 198
|
||||
f 156 122 123 176
|
||||
f 122 86 176 198
|
||||
f 11 178 12 194
|
||||
f 29 141 20 194
|
||||
f 92 108 149 197
|
||||
f 156 176 123 192
|
||||
f 82 22 56 187
|
||||
f 160 104 123 176
|
||||
f 95 85 49 177
|
||||
f 48 40 45 175
|
||||
f 84 59 136 181
|
||||
f 51 37 42 180
|
||||
f 105 159 49 168
|
||||
f 13 187 117 196
|
||||
f 43 179 52 190
|
||||
f 139 174 189 197
|
||||
f 134 109 131 183
|
||||
f 160 86 143 176
|
||||
f 96 1 25 178
|
||||
f 114 111 147 191
|
||||
f 59 55 58 181
|
||||
f 19 26 3 174
|
||||
f 99 195 86 198
|
||||
f 110 115 82 195
|
||||
f 155 187 82 195
|
||||
f 60 62 59 181
|
||||
f 71 74 72 184
|
||||
f 25 178 15 198
|
||||
f 158 103 119 185
|
||||
f 152 140 46 189
|
||||
f 175 194 164 196
|
||||
f 43 44 52 179
|
||||
f 164 172 187 195
|
||||
f 59 62 136 181
|
||||
f 100 157 127 192
|
||||
f 93 104 143 193
|
||||
f 15 25 11 178
|
||||
f 59 58 60 181
|
||||
f 73 61 122 198
|
||||
f 99 86 80 198
|
||||
f 54 51 42 180
|
||||
f 102 119 103 185
|
||||
f 67 71 66 184
|
||||
f 71 72 66 184
|
||||
f 39 33 190 191
|
||||
f 64 63 65 182
|
||||
f 152 139 26 189
|
||||
f 160 123 122 176
|
||||
f 39 38 33 191
|
||||
f 132 88 133 186
|
||||
f 21 187 13 196
|
||||
f 92 186 87 197
|
||||
f 124 79 70 193
|
||||
f 2 26 139 174
|
||||
f 76 109 138 183
|
||||
f 114 39 33 190
|
||||
f 38 47 48 191
|
||||
f 117 13 142 187
|
||||
f 142 155 117 187
|
||||
f 153 152 46 189
|
||||
f 25 1 11 178
|
||||
f 41 147 42 180
|
||||
f 42 111 54 180
|
||||
f 98 13 117 196
|
||||
f 122 61 86 198
|
||||
f 105 83 128 168
|
||||
f 176 192 166 193
|
||||
f 107 112 85 177
|
||||
f 122 86 160 176
|
||||
f 41 147 180 191
|
||||
f 76 74 71 184
|
||||
f 13 21 142 187
|
||||
f 2 174 139 197
|
||||
f 131 71 67 184
|
||||
f 85 146 14 177
|
||||
f 142 82 155 187
|
||||
f 36 130 50 189
|
||||
f 97 87 83 197
|
||||
f 87 92 88 186
|
||||
f 41 125 47 191
|
||||
f 42 147 111 180
|
||||
f 83 168 105 197
|
||||
f 155 99 117 195
|
||||
f 155 82 115 195
|
||||
f 45 151 16 175
|
||||
f 57 102 103 185
|
||||
f 49 85 14 177
|
||||
f 158 133 103 185
|
||||
f 39 190 114 191
|
||||
f 44 144 116 179
|
||||
f 115 93 143 195
|
||||
f 8 98 9 196
|
||||
f 1 144 11 178
|
||||
f 63 100 127 182
|
||||
f 168 186 173 197
|
||||
f 146 85 112 177
|
||||
f 139 189 153 197
|
||||
f 108 153 149 197
|
||||
f 52 44 53 179
|
||||
f 32 28 31 188
|
||||
f 44 116 53 179
|
||||
f 108 92 87 197
|
||||
f 21 22 142 187
|
||||
f 176 195 164 198
|
||||
f 90 106 107 183
|
||||
f 10 11 12 194
|
||||
f 138 107 95 183
|
||||
f 82 142 22 187
|
||||
f 28 27 17 188
|
||||
f 7 21 13 196
|
||||
f 131 76 71 184
|
||||
f 100 101 157 192
|
||||
f 176 193 172 195
|
||||
f 20 16 9 194
|
||||
f 152 26 19 174
|
||||
f 88 132 75 186
|
||||
f 164 194 178 198
|
||||
f 129 31 17 188
|
||||
f 57 103 137 185
|
||||
f 127 65 63 182
|
||||
f 159 105 128 168
|
||||
f 139 152 153 189
|
||||
f 138 109 107 183
|
||||
f 137 103 133 185
|
||||
f 79 89 78 193
|
||||
f 94 43 52 190
|
||||
f 16 48 45 175
|
||||
f 25 15 61 198
|
||||
f 36 46 34 189
|
||||
f 12 29 20 194
|
||||
f 75 87 88 186
|
||||
f 77 127 157 192
|
||||
f 9 118 10 194
|
||||
f 111 114 94 190
|
||||
f 97 83 105 197
|
||||
f 99 143 86 195
|
||||
f 80 15 118 198
|
||||
f 8 151 7 196
|
||||
f 124 104 79 193
|
||||
f 134 90 109 183
|
||||
f 39 114 147 191
|
||||
f 33 43 114 190
|
||||
f 79 93 89 193
|
||||
f 77 123 124 192
|
||||
f 36 50 46 189
|
||||
f 79 104 93 193
|
||||
f 31 28 17 188
|
||||
f 97 105 139 197
|
||||
f 61 80 86 198
|
||||
f 139 105 2 197
|
||||
f 109 90 107 183
|
||||
f 8 7 13 196
|
||||
f 143 99 115 195
|
||||
f 98 8 13 196
|
||||
f 47 38 39 191
|
||||
f 41 47 147 191
|
||||
f 153 46 50 189
|
||||
f 157 101 123 192
|
||||
f 94 114 43 190
|
||||
f 115 99 155 195
|
||||
f 157 123 77 192
|
||||
f 12 20 10 194
|
||||
f 156 123 101 192
|
||||
f 61 15 80 198
|
||||
f 20 9 10 194
|
||||
f 47 39 147 191
|
||||
f 97 108 87 197
|
||||
f 139 153 108 197
|
||||
f 139 108 97 197
|
||||
f 181 158 81 136
|
||||
f 181 81 158 163
|
||||
f 69 183 78 134
|
||||
f 78 183 69 166
|
||||
f 185 161 186 163
|
||||
f 185 186 161 133
|
||||
f 180 35 189 37
|
||||
f 180 189 35 165
|
||||
f 179 121 190 167
|
||||
f 179 190 121 52
|
||||
f 177 3 4 14
|
||||
f 177 4 3 174
|
||||
f 55 181 53 58
|
||||
f 55 53 181 179
|
||||
f 145 53 181 58
|
||||
f 145 181 53 179
|
||||
f 100 192 91 101
|
||||
f 100 91 192 170
|
||||
f 154 91 192 101
|
||||
f 154 192 91 170
|
||||
f 196 129 151 7
|
||||
f 196 151 129 175
|
||||
f 189 149 130 50
|
||||
f 189 130 149 173
|
||||
f 116 178 144 1
|
||||
f 116 144 178 179
|
||||
@@ -0,0 +1,278 @@
|
||||
v 0 1 0
|
||||
v 1 1 0
|
||||
v 2 1 0
|
||||
v 3 1 0
|
||||
v 4 1 0
|
||||
v 5 1 0
|
||||
v 6 1 0
|
||||
v 7 1 0
|
||||
v 8 1 0
|
||||
v 9 1 0
|
||||
v 10 1 0
|
||||
v 0 0 0
|
||||
v 1 0 0
|
||||
v 2 0 0
|
||||
v 3 0 0
|
||||
v 4 0 0
|
||||
v 5 0 0
|
||||
v 6 0 0
|
||||
v 7 0 0
|
||||
v 8 0 0
|
||||
v 9 0 0
|
||||
v 10 0 0
|
||||
v 0 1 2
|
||||
v 1 1 2
|
||||
v 2 1 2
|
||||
v 3 1 2
|
||||
v 4 1 2
|
||||
v 5 1 2
|
||||
v 6 1 2
|
||||
v 7 1 2
|
||||
v 8 1 2
|
||||
v 9 1 2
|
||||
v 10 1 2
|
||||
v 0 2 2
|
||||
v 1 2 2
|
||||
v 2 2 2
|
||||
v 3 2 2
|
||||
v 4 2 2
|
||||
v 5 2 2
|
||||
v 6 2 2
|
||||
v 7 2 2
|
||||
v 8 2 2
|
||||
v 9 2 2
|
||||
v 10 2 2
|
||||
v 1 0 1
|
||||
v 2 0 1
|
||||
v 3 0 1
|
||||
v 4 0 1
|
||||
v 5 0 1
|
||||
v 6 0 1
|
||||
v 7 0 1
|
||||
v 8 0 1
|
||||
v 9 0 1
|
||||
v 10 0 1
|
||||
v 0 0 2
|
||||
v 1 0 2
|
||||
v 2 0 2
|
||||
v 3 0 2
|
||||
v 4 0 2
|
||||
v 5 0 2
|
||||
v 6 0 2
|
||||
v 7 0 2
|
||||
v 8 0 2
|
||||
v 9 0 2
|
||||
v 10 0 2
|
||||
v 10 1 1
|
||||
v 10 2 0
|
||||
v 9 2 0
|
||||
v 8 2 0
|
||||
v 7 2 0
|
||||
v 6 2 0
|
||||
v 5 2 0
|
||||
v 4 2 0
|
||||
v 3 2 0
|
||||
v 2 2 0
|
||||
v 1 2 0
|
||||
v 0 2 0
|
||||
v 10 2 1
|
||||
v 9 2 1
|
||||
v 8 2 1
|
||||
v 7 2 1
|
||||
v 6 2 1
|
||||
v 5 2 1
|
||||
v 4 2 1
|
||||
v 3 2 1
|
||||
v 2 2 1
|
||||
v 1 2 1
|
||||
v 0 2 1
|
||||
v 0 1 1
|
||||
v 0 0 1
|
||||
f 36 86 25 24
|
||||
f 1 87 88 89
|
||||
f 12 13 1 45
|
||||
f 85 38 37 26
|
||||
f 87 35 23 24
|
||||
f 48 85 4 47
|
||||
f 61 28 49 60
|
||||
f 46 14 2 3
|
||||
f 9 31 8 52
|
||||
f 85 37 25 26
|
||||
f 19 7 18 51
|
||||
f 61 28 50 49
|
||||
f 49 28 27 60
|
||||
f 85 5 4 73
|
||||
f 3 85 4 74
|
||||
f 28 61 50 29
|
||||
f 32 31 43 79
|
||||
f 23 45 90 89
|
||||
f 28 39 40 82
|
||||
f 10 54 53 21
|
||||
f 48 85 47 26
|
||||
f 48 85 5 4
|
||||
f 7 50 18 51
|
||||
f 50 28 29 6
|
||||
f 85 4 74 73
|
||||
f 88 87 23 89
|
||||
f 77 1 76 87
|
||||
f 13 46 14 2
|
||||
f 1 12 45 90
|
||||
f 87 35 34 23
|
||||
f 1 2 87 89
|
||||
f 9 53 20 21
|
||||
f 29 28 82 6
|
||||
f 29 82 7 6
|
||||
f 48 49 16 5
|
||||
f 25 47 58 46
|
||||
f 15 48 16 4
|
||||
f 16 48 5 4
|
||||
f 2 1 45 89
|
||||
f 1 2 76 87
|
||||
f 8 30 7 51
|
||||
f 35 86 36 24
|
||||
f 45 1 90 89
|
||||
f 76 2 86 87
|
||||
f 80 30 41 81
|
||||
f 85 5 73 84
|
||||
f 30 62 29 51
|
||||
f 50 29 7 6
|
||||
f 23 24 45 89
|
||||
f 77 1 87 88
|
||||
f 76 2 75 86
|
||||
f 48 85 26 27
|
||||
f 2 86 87 24
|
||||
f 3 74 75 86
|
||||
f 3 85 74 86
|
||||
f 3 24 86 2
|
||||
f 2 3 75 86
|
||||
f 23 87 24 89
|
||||
f 30 80 41 42
|
||||
f 28 5 27 83
|
||||
f 30 29 41 81
|
||||
f 47 58 59 26
|
||||
f 15 48 4 47
|
||||
f 88 87 34 23
|
||||
f 87 86 35 24
|
||||
f 13 2 1 45
|
||||
f 55 23 45 90
|
||||
f 86 85 36 25
|
||||
f 13 46 2 45
|
||||
f 46 25 24 57
|
||||
f 5 73 84 72
|
||||
f 36 85 37 25
|
||||
f 3 85 86 25
|
||||
f 25 3 24 86
|
||||
f 85 84 38 27
|
||||
f 10 11 66 54
|
||||
f 59 48 26 27
|
||||
f 48 47 59 26
|
||||
f 46 25 57 58
|
||||
f 23 56 55 45
|
||||
f 85 48 5 27
|
||||
f 85 38 26 27
|
||||
f 23 24 56 45
|
||||
f 46 24 2 45
|
||||
f 3 25 24 46
|
||||
f 3 24 2 46
|
||||
f 24 46 57 45
|
||||
f 24 57 56 45
|
||||
f 87 2 24 89
|
||||
f 24 2 45 89
|
||||
f 47 25 3 46
|
||||
f 3 15 4 47
|
||||
f 10 11 54 22
|
||||
f 14 15 3 47
|
||||
f 46 14 3 47
|
||||
f 49 28 5 27
|
||||
f 48 49 5 27
|
||||
f 47 25 58 26
|
||||
f 85 5 84 27
|
||||
f 47 85 3 26
|
||||
f 9 80 31 79
|
||||
f 47 25 26 3
|
||||
f 3 85 25 26
|
||||
f 85 47 3 4
|
||||
f 48 49 27 60
|
||||
f 59 48 27 60
|
||||
f 31 9 53 52
|
||||
f 50 61 62 29
|
||||
f 33 32 78 66
|
||||
f 31 80 30 42
|
||||
f 40 29 82 81
|
||||
f 63 62 30 51
|
||||
f 30 63 51 52
|
||||
f 41 29 40 81
|
||||
f 33 32 66 54
|
||||
f 9 80 68 69
|
||||
f 82 71 70 7
|
||||
f 5 84 83 72
|
||||
f 32 43 78 79
|
||||
f 29 28 40 82
|
||||
f 5 84 27 83
|
||||
f 33 32 44 78
|
||||
f 9 80 79 68
|
||||
f 8 7 19 51
|
||||
f 28 27 39 83
|
||||
f 28 39 82 83
|
||||
f 28 50 49 6
|
||||
f 65 64 32 53
|
||||
f 82 71 7 6
|
||||
f 29 82 81 7
|
||||
f 81 70 8 7
|
||||
f 84 38 27 83
|
||||
f 27 38 39 83
|
||||
f 32 43 44 78
|
||||
f 9 31 32 79
|
||||
f 31 80 42 79
|
||||
f 31 42 43 79
|
||||
f 67 78 10 11
|
||||
f 32 9 10 53
|
||||
f 62 50 29 51
|
||||
f 71 82 83 6
|
||||
f 49 16 5 17
|
||||
f 81 82 70 7
|
||||
f 50 49 6 17
|
||||
f 79 68 67 10
|
||||
f 79 9 68 10
|
||||
f 50 6 18 17
|
||||
f 78 10 11 66
|
||||
f 78 79 67 10
|
||||
f 32 9 79 10
|
||||
f 78 32 79 66
|
||||
f 79 32 10 66
|
||||
f 78 79 10 66
|
||||
f 9 10 53 21
|
||||
f 82 28 83 6
|
||||
f 71 83 72 6
|
||||
f 69 81 70 8
|
||||
f 64 31 53 52
|
||||
f 28 5 83 6
|
||||
f 83 5 72 6
|
||||
f 80 30 81 8
|
||||
f 28 49 5 6
|
||||
f 64 63 31 52
|
||||
f 80 81 69 8
|
||||
f 9 80 69 8
|
||||
f 7 50 6 18
|
||||
f 80 9 31 8
|
||||
f 80 31 30 8
|
||||
f 31 63 30 52
|
||||
f 31 30 8 52
|
||||
f 30 81 8 7
|
||||
f 30 29 81 7
|
||||
f 19 8 51 52
|
||||
f 33 65 32 54
|
||||
f 49 5 6 17
|
||||
f 10 54 21 22
|
||||
f 29 50 7 51
|
||||
f 30 29 7 51
|
||||
f 65 32 54 53
|
||||
f 9 53 52 20
|
||||
f 31 9 32 53
|
||||
f 64 31 32 53
|
||||
f 32 10 66 53
|
||||
f 66 10 54 53
|
||||
f 32 66 54 53
|
||||
f 8 30 51 52
|
||||
f 8 9 52 20
|
||||
f 19 8 52 20
|
||||
@@ -0,0 +1,454 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Description\n",
|
||||
"\n",
|
||||
"This notebook intends to gather all the functionalities you'll have to implement for assignment 2.2.\n",
|
||||
"\n",
|
||||
"# Load libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import igl\n",
|
||||
"import meshplot as mp\n",
|
||||
"import time\n",
|
||||
"\n",
|
||||
"import sys as _sys\n",
|
||||
"_sys.path.append(\"../src\")\n",
|
||||
"from elasticsolid import *\n",
|
||||
"from elasticenergy import *\n",
|
||||
"from matplotlib import gridspec\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"shadingOptions = {\n",
|
||||
" \"flat\":True,\n",
|
||||
" \"wireframe\":False, \n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"rot = np.array(\n",
|
||||
" [[1, 0, 0 ],\n",
|
||||
" [0, 0, 1],\n",
|
||||
" [0, -1, 0 ]]\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Load mesh\n",
|
||||
"\n",
|
||||
"Several meshes are available for you to play with under `data/`: `ball.obj`, `dinosaur.obj`, and `beam.obj`. You can also uncomment the few commented lines below to manipulate a simple mesh made out of 2 tetrahedra."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "fb09ceba0f474ff6a670b5386fe53817",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
" v, _, _, t, _, _ = igl.read_obj(\"../data/dinosaur.obj\")\n",
|
||||
"#v, _, _, t, _, _ = igl.read_obj(\"../data/beam.obj\")\n",
|
||||
"\n",
|
||||
"# t = np.array([\n",
|
||||
"# [0, 1, 2, 3],\n",
|
||||
"# [1, 2, 3, 4]\n",
|
||||
"# ])\n",
|
||||
"# v = np.array([\n",
|
||||
"# [0., 0., 0.],\n",
|
||||
"# [1., 0., 0.],\n",
|
||||
"# [0., 1., 0.],\n",
|
||||
"# [0., 0., 1.],\n",
|
||||
"# [2/3, 2/3, 2/3]\n",
|
||||
"# ])\n",
|
||||
"\n",
|
||||
"be = igl.edges(igl.boundary_facets(t))\n",
|
||||
"e = igl.edges(t)\n",
|
||||
"\n",
|
||||
"aabb = np.max(v, axis=0) - np.min(v, axis=0)\n",
|
||||
"length_scale = np.mean(aabb)\n",
|
||||
"\n",
|
||||
"p = mp.plot(v @ rot.T, t, shading=shadingOptions)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Linear/Non-Linear Elastic Solid\n",
|
||||
"\n",
|
||||
"## Instantiation\n",
|
||||
"\n",
|
||||
"We first specify the elasticity model to use for the elastic solid, as well as pinned vertices, and volumetric forces."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"rho = 131 # [kg.m-3]\n",
|
||||
"young = 10e6 # [Pa] \n",
|
||||
"poisson = 0.2\n",
|
||||
"force_mass = np.zeros(shape = (3,))\n",
|
||||
"force_mass[2] = - rho * 9.81\n",
|
||||
"\n",
|
||||
"minX = np.min(v[:, 0])\n",
|
||||
"pin_idx = np.arange(v.shape[0])[v[:, 0] < minX + 0.2*aabb[0]]\n",
|
||||
"\n",
|
||||
"lin_ee = LinearElasticEnergy(young, poisson)\n",
|
||||
"neo_ee = NeoHookeanElasticEnergy(young, poisson)\n",
|
||||
"\n",
|
||||
"lin_solid = ElasticSolid(v, t, lin_ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)\n",
|
||||
"neo_solid = ElasticSolid(v, t, neo_ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)\n",
|
||||
"\n",
|
||||
"solid = neo_solid\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Deform the mesh\n",
|
||||
"\n",
|
||||
"This should now involve elastic forces computation."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/opt/notebooks/assignment_2_2/notebook/../src/elasticenergy.py:145: RuntimeWarning: invalid value encountered in log\n",
|
||||
" self.logJ = np.log(np.linalg.det(jac))\n",
|
||||
"/opt/notebooks/assignment_2_2/notebook/../src/elasticenergy.py:131: RuntimeWarning: invalid value encountered in log\n",
|
||||
" j = np.log(np.linalg.det(jac))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "327564baf8ad4d3fb73b223d8fd921f9",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-0.865849…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"v_def = v.copy()\n",
|
||||
"v_def[:, 0] *= 2.\n",
|
||||
"solid.update_def_shape(v_def)\n",
|
||||
"\n",
|
||||
"p = mp.plot(solid.v_def @ rot.T, solid.t, shading=shadingOptions)\n",
|
||||
"p.add_points(solid.v_def[solid.pin_idx, :] @ rot.T, shading={\"point_color\":\"black\", \"point_size\": 0.1 * length_scale})\n",
|
||||
"forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))\n",
|
||||
"p.add_lines(solid.v_def @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)\n",
|
||||
"p.add_edges(v @ rot.T, be, shading={\"line_color\": \"blue\"})\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Find equilibrium\n",
|
||||
"\n",
|
||||
"We compare different methods: number of steps, computation time."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"n_steps = 1000\n",
|
||||
"thresh = 1.\n",
|
||||
"v_init = v.copy()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Gradient descent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "59861d218fad43e6b57b45bed934c9a3",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987468…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"report_GD = equilibrium_convergence_report_GD(solid, v_init, n_steps, 5e-5, thresh=thresh)\n",
|
||||
"energies_el_GD = report_GD['energies_el']\n",
|
||||
"energies_ext_GD = report_GD['energies_ext']\n",
|
||||
"energy_GD = energies_el_GD + energies_ext_GD\n",
|
||||
"residuals_GD = report_GD['residuals']\n",
|
||||
"times_GD = report_GD['times']\n",
|
||||
"idx_stop_GD = report_GD['idx_stop']\n",
|
||||
"v_def_GD = solid.v_def.copy()\n",
|
||||
"\n",
|
||||
"# Lastly, plot the resulting shape\n",
|
||||
"p = mp.plot(v_def_GD @ rot.T, solid.t, shading=shadingOptions)\n",
|
||||
"forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))\n",
|
||||
"p.add_lines(v_def_GD @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)\n",
|
||||
"p.add_points(v_def_GD[pin_idx, :] @ rot.T, shading={\"point_color\":\"black\", \"point_size\": 0.1 * length_scale})\n",
|
||||
"p.add_edges(v @ rot.T, be, shading={\"line_color\": \"blue\"})"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BFGS\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "4fac36847fef413586d1026fc645eeae",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-3.283369…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"report_BFGS = equilibrium_convergence_report_BFGS(solid, v_init, n_steps, 1e-7, thresh=thresh)\n",
|
||||
"energies_el_BFGS = report_BFGS['energies_el']\n",
|
||||
"energies_ext_BFGS = report_BFGS['energies_ext']\n",
|
||||
"energy_BFGS = energies_el_BFGS + energies_ext_BFGS\n",
|
||||
"residuals_BFGS = report_BFGS['residuals']\n",
|
||||
"times_BFGS = report_BFGS['times']\n",
|
||||
"idx_stop_BFGS = report_BFGS['idx_stop']\n",
|
||||
"v_def_BFGS = solid.v_def.copy()\n",
|
||||
"\n",
|
||||
"# Lastly, plot the resulting shape\n",
|
||||
"p = mp.plot(v_def_BFGS @ rot.T, solid.t, shading=shadingOptions)\n",
|
||||
"forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))\n",
|
||||
"p.add_lines(v_def_BFGS @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)\n",
|
||||
"p.add_points(v_def_BFGS[pin_idx, :] @ rot.T, shading={\"point_color\":\"black\", \"point_size\": 0.1 * length_scale})\n",
|
||||
"p.add_edges(v @ rot.T, be, shading={\"line_color\": \"blue\"})"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Compare the different algorithms"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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57LpAonIV4m//gS8SesVeFc3/jxyvb/N1XhFdB3wSGM/dzGcl84Ry+rF2sT57o43xFyBVxie7sf7p4ht+uD12pX5r+dpMMEeb1jwPbwibR3evK8L/HWDgVcjYv8OuCzZ/7b10iseL3MuqGkN8eF3R090zu1sZkXAN865hsMhmNn9wMfOuUf8z28BlzvnPk1kvCKSXObdn+odoItzbkVyo2l/zLtD/SLgROfcc8mOR6S1a9VztBpyzq3Du9rpF+DNS4mYLPkC3nBL6BfBQLx754iIyBYys/3N7Egz6+8P8T2D1xOoqRkiUWjVhZaZPY03TDHIzBaa2a/xbsr4azObAkzHu4EeeGP7K81sBt7/Zi91zq1MRtwiIu1IJnAj3lzAl/CGtvd1zq1PalQibUSrHzoUERERaatadY+WiIiISFumQktEREQkIK32PlqdO3d2/fr1C7SN9evXk5/f6A2t271UzT1V8wblrtxTS6rmDco9Wbl//vnnK5xzmz06qtUWWv369eOzzz5recOtUFpaSklJSaBttFapmnuq5g3KXbmnllTNG5R7snL3b8i7GQ0dioiIiAREhZaIiIhIQFRoiYiIiAREhZaIiIhIQFrtZHgREQlOdXU1CxcupKKiItmhBKK4uJiZM2cmO4ykUO7B5J6enk6HDh3o3LkzaWnR91Op0BIRSUELFy6ksLCQfv36YWbJDifuysrKKCwsTHYYSaHc45+7c47q6mqWLl3KwoUL6dOnT9T7auhQRCQFVVRU0KlTp3ZZZInEm5mRlZXFtttuy/r1sT3mU4WWiEiKUpElEptYhgzD+wQQh4iIiIigQktERFJUv379ePPNNwG4+eabOeuss5IcUdu2fPlyBg0alPQLLN577z0GDRq0Rfsec8wxvPbaa3GNR4WWiIi0OuPHj2ePPfYgPz+frl27sscee3DvvffinAukvSuvvJKHHnpoq48zd+5czIyampomt7n22mvJzMyksLCQwsJCBg4cyAUXXMDixYu3uv2gmBnfffdds9vccsstnHHGGeTk5ADw7LPPsvfee5OXl9foY3G++uorRowYQV5eHiNGjOCrr76qt/6vf/0r3bt3p7i4mDPPPJPKysrwulWrVnH00UeTn59P3759eeqpp8LrfvrTn/LNN9+EP0cW1C25/PLLueqqq6LaNloqtBpRXlPB0oq1yQ5DRCQl3XHHHVx44YVceumlLFmyhKVLl3L//ffzwQcfUFVV1eg+tbW1CY5y65xwwgmUlZWxatUqnn/+eZYsWcKIESNadbHVnMrKSh599FFOOeWU8LJtttmGiy66iMsvv3yz7auqqjjyyCM55ZRTWL16NaeddhpHHnlk+Pv7+uuvc8stt/DWW28Line truncated
|
||||
"text/plain": [
|
||||
"<Figure size 720x432 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"cmap = plt.get_cmap('viridis')\n",
|
||||
"colors = cmap(np.linspace(0., 1., 4))\n",
|
||||
"\n",
|
||||
"gs = gridspec.GridSpec(nrows=1, ncols=1, width_ratios=[1], height_ratios=[1])\n",
|
||||
"fig = plt.figure(figsize=(10, 6))\n",
|
||||
"\n",
|
||||
"axTmp = plt.subplot(gs[0, 0])\n",
|
||||
"axTmp.plot(times_GD[:idx_stop_GD+1], residuals_GD[:idx_stop_GD+1], c=colors[0], \n",
|
||||
" label=\"Gradient Descent ({:}its)\".format(idx_stop_GD))\n",
|
||||
"axTmp.plot(times_BFGS[:idx_stop_BFGS+1], residuals_BFGS[:idx_stop_BFGS+1], c=colors[2], \n",
|
||||
" label=\"BFGS ({:}its)\".format(idx_stop_BFGS))\n",
|
||||
"y_lim = axTmp.get_ylim()\n",
|
||||
"axTmp.set_title(\"Residuals as optimization goes\", fontsize=14)\n",
|
||||
"axTmp.set_xlabel(\"Computation time [s]\", fontsize=12)\n",
|
||||
"axTmp.set_ylabel(\"Force residuals [N]\", fontsize=12)\n",
|
||||
"axTmp.set_ylim(y_lim)\n",
|
||||
"plt.legend(fontsize=12)\n",
|
||||
"plt.grid()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 720x432 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"gs = gridspec.GridSpec(nrows=1, ncols=1, width_ratios=[1], height_ratios=[1])\n",
|
||||
"fig = plt.figure(figsize=(10, 6))\n",
|
||||
"\n",
|
||||
"axTmp = plt.subplot(gs[0, 0])\n",
|
||||
"axTmp.plot(times_GD[:idx_stop_GD+1], energy_GD[:idx_stop_GD+1], c=colors[0], \n",
|
||||
" label=\"Gradient Descent ({:}its)\".format(idx_stop_GD))\n",
|
||||
"axTmp.plot(times_BFGS[:idx_stop_BFGS+1], energy_BFGS[:idx_stop_BFGS+1], c=colors[2], \n",
|
||||
" label=\"BFGS ({:}its)\".format(idx_stop_BFGS))\n",
|
||||
"y_lim = axTmp.get_ylim()\n",
|
||||
"axTmp.set_title(\"Total energy as optimization goes\", fontsize=14)\n",
|
||||
"axTmp.set_xlabel(\"Computation time [s]\", fontsize=12)\n",
|
||||
"axTmp.set_ylabel(\"Energy [J]\", fontsize=12)\n",
|
||||
"axTmp.set_ylim(y_lim)\n",
|
||||
"plt.legend(fontsize=12)\n",
|
||||
"plt.grid()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.7"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": true,
|
||||
"sideBar": true,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": true,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Description\n",
|
||||
"\n",
|
||||
"This notebook intends to gather all the functionalities you'll have to implement for assignment 2.2.\n",
|
||||
"\n",
|
||||
"# Load libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import igl\n",
|
||||
"import meshplot as mp\n",
|
||||
"import time\n",
|
||||
"\n",
|
||||
"import sys as _sys\n",
|
||||
"_sys.path.append(\"../src\")\n",
|
||||
"from elasticsolid import *\n",
|
||||
"from elasticenergy import *\n",
|
||||
"from matplotlib import gridspec\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"shadingOptions = {\n",
|
||||
" \"flat\":True,\n",
|
||||
" \"wireframe\":False, \n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"rot = np.array(\n",
|
||||
" [[1, 0, 0 ],\n",
|
||||
" [0, 0, 1],\n",
|
||||
" [0, -1, 0 ]]\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Load mesh\n",
|
||||
"\n",
|
||||
"Several meshes are available for you to play with under `data/`: `ball.obj`, `dinosaur.obj`, and `beam.obj`. You can also uncomment the few commented lines below to manipulate a simple mesh made out of 2 tetrahedra."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"v, _, _, t, _, _ = igl.read_obj(\"../data/beam.obj\")\n",
|
||||
"aabb = np.max(v, axis=0) - np.min(v, axis=0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Linear/Non-Linear Elastic Solid\n",
|
||||
"\n",
|
||||
"## Instantiation\n",
|
||||
"\n",
|
||||
"We first specify the elasticity model to use for the elastic solid, as well as pinned vertices, and volumetric forces."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"rho = 131 # [kg.m-3]\n",
|
||||
"young = 10e6 # [Pa] \n",
|
||||
"poisson = 0.2\n",
|
||||
"force_mass = np.zeros(shape = (3,))\n",
|
||||
"force_mass[2] = - rho * 9.81\n",
|
||||
"\n",
|
||||
"minX = np.min(v[:, 0])\n",
|
||||
"pin_idx = np.arange(v.shape[0])[v[:, 0] < minX + 0.2*aabb[0]]\n",
|
||||
"\n",
|
||||
"ee = LinearElasticEnergy(young, poisson)\n",
|
||||
"# ee = NeoHookeanElasticEnergy(young, poisson)\n",
|
||||
"solid = ElasticSolid(v, t, ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Validate Elastic Energy Gradient (Elastic Forces) using Finite Differences on Elastic Energy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 432x288 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"fd_validation_elastic(solid)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Validate External Energy Gradient (External Forces) using Finite Differences on External Energy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 432x288 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"fd_validation_ext(solid)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.7"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": true,
|
||||
"sideBar": true,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": true,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,454 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Description\n",
|
||||
"\n",
|
||||
"This notebook intends to gather all the functionalities you'll have to implement for assignment 2.2.\n",
|
||||
"\n",
|
||||
"# Load libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import igl\n",
|
||||
"import meshplot as mp\n",
|
||||
"import time\n",
|
||||
"\n",
|
||||
"import sys as _sys\n",
|
||||
"_sys.path.append(\"../src\")\n",
|
||||
"from elasticsolid import *\n",
|
||||
"from elasticenergy import *\n",
|
||||
"from matplotlib import gridspec\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"shadingOptions = {\n",
|
||||
" \"flat\":True,\n",
|
||||
" \"wireframe\":False, \n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"rot = np.array(\n",
|
||||
" [[1, 0, 0 ],\n",
|
||||
" [0, 0, 1],\n",
|
||||
" [0, -1, 0 ]]\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Load mesh\n",
|
||||
"\n",
|
||||
"Several meshes are available for you to play with under `data/`: `ball.obj`, `dinosaur.obj`, and `beam.obj`. You can also uncomment the few commented lines below to manipulate a simple mesh made out of 2 tetrahedra."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "fb09ceba0f474ff6a670b5386fe53817",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
" v, _, _, t, _, _ = igl.read_obj(\"../data/dinosaur.obj\")\n",
|
||||
"#v, _, _, t, _, _ = igl.read_obj(\"../data/beam.obj\")\n",
|
||||
"\n",
|
||||
"# t = np.array([\n",
|
||||
"# [0, 1, 2, 3],\n",
|
||||
"# [1, 2, 3, 4]\n",
|
||||
"# ])\n",
|
||||
"# v = np.array([\n",
|
||||
"# [0., 0., 0.],\n",
|
||||
"# [1., 0., 0.],\n",
|
||||
"# [0., 1., 0.],\n",
|
||||
"# [0., 0., 1.],\n",
|
||||
"# [2/3, 2/3, 2/3]\n",
|
||||
"# ])\n",
|
||||
"\n",
|
||||
"be = igl.edges(igl.boundary_facets(t))\n",
|
||||
"e = igl.edges(t)\n",
|
||||
"\n",
|
||||
"aabb = np.max(v, axis=0) - np.min(v, axis=0)\n",
|
||||
"length_scale = np.mean(aabb)\n",
|
||||
"\n",
|
||||
"p = mp.plot(v @ rot.T, t, shading=shadingOptions)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Linear/Non-Linear Elastic Solid\n",
|
||||
"\n",
|
||||
"## Instantiation\n",
|
||||
"\n",
|
||||
"We first specify the elasticity model to use for the elastic solid, as well as pinned vertices, and volumetric forces."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"rho = 131 # [kg.m-3]\n",
|
||||
"young = 10e6 # [Pa] \n",
|
||||
"poisson = 0.2\n",
|
||||
"force_mass = np.zeros(shape = (3,))\n",
|
||||
"force_mass[2] = - rho * 9.81\n",
|
||||
"\n",
|
||||
"minX = np.min(v[:, 0])\n",
|
||||
"pin_idx = np.arange(v.shape[0])[v[:, 0] < minX + 0.2*aabb[0]]\n",
|
||||
"\n",
|
||||
"lin_ee = LinearElasticEnergy(young, poisson)\n",
|
||||
"neo_ee = NeoHookeanElasticEnergy(young, poisson)\n",
|
||||
"\n",
|
||||
"lin_solid = ElasticSolid(v, t, lin_ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)\n",
|
||||
"neo_solid = ElasticSolid(v, t, neo_ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)\n",
|
||||
"\n",
|
||||
"solid = neo_solid\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Deform the mesh\n",
|
||||
"\n",
|
||||
"This should now involve elastic forces computation."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/opt/notebooks/assignment_2_2/notebook/../src/elasticenergy.py:145: RuntimeWarning: invalid value encountered in log\n",
|
||||
" self.logJ = np.log(np.linalg.det(jac))\n",
|
||||
"/opt/notebooks/assignment_2_2/notebook/../src/elasticenergy.py:131: RuntimeWarning: invalid value encountered in log\n",
|
||||
" j = np.log(np.linalg.det(jac))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "327564baf8ad4d3fb73b223d8fd921f9",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-0.865849…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"v_def = v.copy()\n",
|
||||
"v_def[:, 0] *= 2.\n",
|
||||
"solid.update_def_shape(v_def)\n",
|
||||
"\n",
|
||||
"p = mp.plot(solid.v_def @ rot.T, solid.t, shading=shadingOptions)\n",
|
||||
"p.add_points(solid.v_def[solid.pin_idx, :] @ rot.T, shading={\"point_color\":\"black\", \"point_size\": 0.1 * length_scale})\n",
|
||||
"forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))\n",
|
||||
"p.add_lines(solid.v_def @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)\n",
|
||||
"p.add_edges(v @ rot.T, be, shading={\"line_color\": \"blue\"})\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Find equilibrium\n",
|
||||
"\n",
|
||||
"We compare different methods: number of steps, computation time."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"n_steps = 1000\n",
|
||||
"thresh = 1.\n",
|
||||
"v_init = v.copy()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Gradient descent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "59861d218fad43e6b57b45bed934c9a3",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987468…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"report_GD = equilibrium_convergence_report_GD(solid, v_init, n_steps, 5e-5, thresh=thresh)\n",
|
||||
"energies_el_GD = report_GD['energies_el']\n",
|
||||
"energies_ext_GD = report_GD['energies_ext']\n",
|
||||
"energy_GD = energies_el_GD + energies_ext_GD\n",
|
||||
"residuals_GD = report_GD['residuals']\n",
|
||||
"times_GD = report_GD['times']\n",
|
||||
"idx_stop_GD = report_GD['idx_stop']\n",
|
||||
"v_def_GD = solid.v_def.copy()\n",
|
||||
"\n",
|
||||
"# Lastly, plot the resulting shape\n",
|
||||
"p = mp.plot(v_def_GD @ rot.T, solid.t, shading=shadingOptions)\n",
|
||||
"forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))\n",
|
||||
"p.add_lines(v_def_GD @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)\n",
|
||||
"p.add_points(v_def_GD[pin_idx, :] @ rot.T, shading={\"point_color\":\"black\", \"point_size\": 0.1 * length_scale})\n",
|
||||
"p.add_edges(v @ rot.T, be, shading={\"line_color\": \"blue\"})"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BFGS\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "4fac36847fef413586d1026fc645eeae",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-3.283369…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"report_BFGS = equilibrium_convergence_report_BFGS(solid, v_init, n_steps, 1e-7, thresh=thresh)\n",
|
||||
"energies_el_BFGS = report_BFGS['energies_el']\n",
|
||||
"energies_ext_BFGS = report_BFGS['energies_ext']\n",
|
||||
"energy_BFGS = energies_el_BFGS + energies_ext_BFGS\n",
|
||||
"residuals_BFGS = report_BFGS['residuals']\n",
|
||||
"times_BFGS = report_BFGS['times']\n",
|
||||
"idx_stop_BFGS = report_BFGS['idx_stop']\n",
|
||||
"v_def_BFGS = solid.v_def.copy()\n",
|
||||
"\n",
|
||||
"# Lastly, plot the resulting shape\n",
|
||||
"p = mp.plot(v_def_BFGS @ rot.T, solid.t, shading=shadingOptions)\n",
|
||||
"forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))\n",
|
||||
"p.add_lines(v_def_BFGS @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)\n",
|
||||
"p.add_points(v_def_BFGS[pin_idx, :] @ rot.T, shading={\"point_color\":\"black\", \"point_size\": 0.1 * length_scale})\n",
|
||||
"p.add_edges(v @ rot.T, be, shading={\"line_color\": \"blue\"})"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Compare the different algorithms"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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57LpAonIV4m//gS8SesVeFc3/jxyvb/N1XhFdB3wSGM/dzGcl84Ry+rF2sT57o43xFyBVxie7sf7p4ht+uD12pX5r+dpMMEeb1jwPbwibR3evK8L/HWDgVcjYv8OuCzZ/7b10iseL3MuqGkN8eF3R090zu1sZkXAN865hsMhmNn9wMfOuUf8z28BlzvnPk1kvCKSXObdn+odoItzbkVyo2l/zLtD/SLgROfcc8mOR6S1a9VztBpyzq3Du9rpF+DNS4mYLPkC3nBL6BfBQLx754iIyBYys/3N7Egz6+8P8T2D1xOoqRkiUWjVhZaZPY03TDHIzBaa2a/xbsr4azObAkzHu4EeeGP7K81sBt7/Zi91zq1MRtwiIu1IJnAj3lzAl/CGtvd1zq1PalQibUSrHzoUERERaatadY+WiIiISFumQktEREQkIK32PlqdO3d2/fr1C7SN9evXk5/f6A2t271UzT1V8wblrtxTS6rmDco9Wbl//vnnK5xzmz06qtUWWv369eOzzz5recOtUFpaSklJSaBttFapmnuq5g3KXbmnllTNG5R7snL3b8i7GQ0dioiIiAREhZaIiIhIQFRoiYiIiAREhZaIiIhIQFrtZHgREQlOdXU1CxcupKKiItmhBKK4uJiZM2cmO4ykUO7B5J6enk6HDh3o3LkzaWnR91Op0BIRSUELFy6ksLCQfv36YWbJDifuysrKKCwsTHYYSaHc45+7c47q6mqWLl3KwoUL6dOnT9T7auhQRCQFVVRU0KlTp3ZZZInEm5mRlZXFtttuy/r1sT3mU4WWiEiKUpElEptYhgzD+wQQh4iIiIigQktERFJUv379ePPNNwG4+eabOeuss5IcUdu2fPlyBg0alPQLLN577z0GDRq0Rfsec8wxvPbaa3GNR4WWiIi0OuPHj2ePPfYgPz+frl27sscee3DvvffinAukvSuvvJKHHnpoq48zd+5czIyampomt7n22mvJzMyksLCQwsJCBg4cyAUXXMDixYu3uv2gmBnfffdds9vccsstnHHGGeTk5ADw7LPPsvfee5OXl9foY3G++uorRowYQV5eHiNGjOCrr76qt/6vf/0r3bt3p7i4mDPPPJPKysrwulWrVnH00UeTn59P3759eeqpp8LrfvrTn/LNN9+EP0cW1C25/PLLueqqq6LaNloqtBpRXlPB0oq1yQ5DRCQl3XHHHVx44YVceumlLFmyhKVLl3L//ffzwQcfUFVV1eg+tbW1CY5y65xwwgmUlZWxatUqnn/+eZYsWcKIESNadbHVnMrKSh599FFOOeWU8LJtttmGiy66iMsvv3yz7auqqjjyyCM55ZRTWL16NaeddhpHHnlk+Pv7+uuvc8stt/DWW28Line truncated
|
||||
"text/plain": [
|
||||
"<Figure size 720x432 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"cmap = plt.get_cmap('viridis')\n",
|
||||
"colors = cmap(np.linspace(0., 1., 4))\n",
|
||||
"\n",
|
||||
"gs = gridspec.GridSpec(nrows=1, ncols=1, width_ratios=[1], height_ratios=[1])\n",
|
||||
"fig = plt.figure(figsize=(10, 6))\n",
|
||||
"\n",
|
||||
"axTmp = plt.subplot(gs[0, 0])\n",
|
||||
"axTmp.plot(times_GD[:idx_stop_GD+1], residuals_GD[:idx_stop_GD+1], c=colors[0], \n",
|
||||
" label=\"Gradient Descent ({:}its)\".format(idx_stop_GD))\n",
|
||||
"axTmp.plot(times_BFGS[:idx_stop_BFGS+1], residuals_BFGS[:idx_stop_BFGS+1], c=colors[2], \n",
|
||||
" label=\"BFGS ({:}its)\".format(idx_stop_BFGS))\n",
|
||||
"y_lim = axTmp.get_ylim()\n",
|
||||
"axTmp.set_title(\"Residuals as optimization goes\", fontsize=14)\n",
|
||||
"axTmp.set_xlabel(\"Computation time [s]\", fontsize=12)\n",
|
||||
"axTmp.set_ylabel(\"Force residuals [N]\", fontsize=12)\n",
|
||||
"axTmp.set_ylim(y_lim)\n",
|
||||
"plt.legend(fontsize=12)\n",
|
||||
"plt.grid()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAmMAAAGHCAYAAAD89VV0AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAABJ6UlEQVR4nO3deXxU5dn/8c+VdUImJGELIAiCgoiKCIJiVbAuuOLC09aqFfe61da9DxX3/ty7PFatWuterEtF1NYdcV8ryK5SlEV2Akkg+/3745ykk5hlEmZyJjPf9+s1r8yc9brOTDJX7vs+55hzDhEREREJRlrQAYiIiIikMhVjIiIiIgFSMSYiIiISIBVjIiIiIgFSMSYiIiISIBVjIiIiIgFSMSbSyZjZLDO7K+g4pHlm9pCZvRCD7TgzmxyLmFrYx7VmNi+e+xCRlqkYE2kn/4uypcdDUawf1y9aiS8zG++/jz0azboYOCUGu+gDzIzBdjCzgX6soxvNuh04KBb7EJH2yQg6AJFOrE/E86OB+xtN29ax4QTPzDKdc1VBxxE059zmGG1ndSy208o+SoHSeO9HRJqnljGRdnLOra57AMVNTPuJmX1lZpX+z7Pr1jWzZf7Tp/zWimX+9MFmNsPMVptZmZl9ZmZHtzU2MxtnZm+Z2VYzW2lm95hZ14j5s8zsbjP7rZmtN7O1Zna7maVFLJNlZreY2Qo/lo/N7PCI+XWtQkea2UdmVgkcbma5ZvaImZWa2Roz+7WZvVDXUmhm05rqFjOzd83sjy3kdLOZLTazbWa2zMxuNbNQxPz+/rHb6Oe9yMx+0sL20szsajNbbmYVZvaFmU2KmF/XkvRTM3vHzMr9bR5WNx940198XWRraONuSv9432Nmd/jxrTOzi80s28z+ZGbFZvatmZ3aKMb61lN/m021wE7x5080s7fNbJO/j5fNbFjE5v7j//zYX2+Wv16Dbso2HJcTzexV/1gvMLNDmzvW/notfi78ZQrN7GE/h21m9pqZDW+0ndY+2wea2Qf+fjab2YdmtntLsYkETcWYSByY2fHAXcDvgd2BPwB3m9kx/iL7+D/PxmtNq3sdBv4JHAqMAJ4BnjWzXduw7z2AV4Dn/W2cAOwFPNho0ZOBamAccCHwS+DHEfP/itd99VNgD+BhYKaZjWi0nVuA3wC7Ah8Cd/jrHQ8c7MdwQMTyDwK7mtmYiJiH+nH8pYXUyoAzgGHA+cBPgKkR8+8GugATgOF+PsUtbO9i4HLgSj+/f+Ad670aLXcr8Ee8Y/gqMMPMdgCWAyf6ywzHex8vbmF/JwMlwFjgZrzPxnPAEmA03vF9wMz6thBvn4jHVGAr8Ik/P9ff5hhgPLAZ7/3K8ufXHe+J/vontLCfaI7LTXjHZQTwMTDdzMLNJU/rnwuAh/COzyQ/3q3Av8wsB1r/bJtZBjADeMefPxbvd6+mhbhEguec00MPPbbzAUz2fp3qX78LPNhomYeAdyJeO2ByFNv+APhNxOtZwF0tLP8I8JdG0/by99crYhvvN1rmVeAB//lgoBbYsdEyzwF3+8/H+9s8MWJ+GKgEfhIxLRfYBDwUMe0F4N6I17cAn7TxmP8c+Cri9VzgmjasvxKY1mjaLOAx//lAP7+pEfPT8IqnGxsdgx5NvNcvNNru+xGvDVgHPB8xLdM/dpMjpjX5GQF+AJQDJ7SQXy5eEfKDRvmMbrTctcC8dhyXcyPm7+BP+0EzsbT6uQB28bdxYMQy+XhF5VnRfLaBbv7zg9ryWdJDj6AfnbplzMweNK97pdUzgczsd2b2uf9YYmbFHRCipK5heAVZpHeA3Vpaye/KudXv9tlkZqV4rSY7tmHfo4BT/G6aUn8bdbEMjlhubqP1VuF9oQHsjVcwLGi0naMabQP+2zJTt/1M4KO6Cc65MqDx7+j9eN24OWaWDpxKy61imNlkv7twtR/L72h4XP4A/MbM3jezG81sVAvb6gr0Jbr36P2IXGrxWv9afB+bUX+8nXMOWAt8ETGtCq846fX9VRvEPhB4FrjeOfdsxPTBZvaEmX1tZluANXjFY9SfnTYel8jPzyr/Z3OxR/O5GIb3D0Dk8d6Md4zq9t3iZ9s5txGvEH7ZzF40s0vMrH8zMYkkjM4+gP8hvK6gR1pb0Dn3q7rnZnYRMDJ+YYkA3n/o0UyLdDteN9JlwJd43TSPAFktrdRIGvAAXrHS2MqI540H2jv+O3QhzX+9TxPLNT4xoSziuUVsqyUv4uV2Il7LRwHwt+YWNrN9genAdcCv8Lofj8U7Xt4OnfuLmb0MHAkcArxnZv/POXdtC3G05z1qr6aOd0vvwff43YDPAy87537baPZMvPf3XP9nNbCAtn12IuNobVp97M45Z2bQfOzRfC6shXl167X62XbOnW5mv8f7PToWuMnMjnPOvdzC9kUC1albxpxzs4GNkdP8/w7/ZWaf+oNZmxprcxIt/OEXiYGFeF1JkX6A9+VYpwpIb2KZR5xzzzjn5gIr+H5LVGs+A4Y7575q4hHtGZ7/xvty7N3ENla2sN5Xfl6R48G64I2bq+ecq8b7Z+oM//Gsc664he3uD6x0zt3gnPvYOfclMKDxQs65Fc65+5xzPwKmAec0tTHn3Ba81pzW3iOAfSNyMT+3hf6kSv9n4/cx5sw7ueJxvHFnZzWa1x2vZem3zrnXnHMLgTwa/sPdaqxtPC5tEc3nYgHed9J+Ect0xRu3VrfvqD7bzrk5zrlbnHPj8bpYT9uO2EXirrO3jDXlPuDnzrkvzWws3qDeg+tmmtkAYCfgjYDik9RwG96Zkp/iDTieiDeAO3LQ9DLgh2b2FlDhnNuENx7peDObgffldQ0Qom1uAT4ws3uBP+N9ee8KHOOcOzeaDTjnlpjZ48BDZnYp3pdgN7wxUksju8carVdqZg8Ct5jZeuA7vMH9dS1tkR7AGyReCxzWSkhLgB3M7GS8bqzD8f6pqmdmf8A7+WEJ0BXvmLdUQNwGXG9mXwKf4l0X7AC8rrBI55nZErzusvPxisB7/Hnf+HkdZWYzgW3Ou1REPFyDV6gcAhT6LVHgtSxuAtYDZ5vZcrwxXLfhtY7VWYvXqnm4eWfvlrumL8ER7XGJWjSfC/9v9gzgz2Z2Dl7r503AFuAJf1MtfrbNbCe8lsHn8VrKBgF78t/3SyQhJVUx5jfhj8P7EqybnN1osZ8ATzvndHaNxI1z7jm/O/wyvDPcvgHOd85FXsDzUuBOvLPyVuINjL4Eb+zU23hfsL+njcWYc26umR0I3Ai8hdcSshTvrLi2OB3vjL1bgX54rdAf8d/LOTTnMrzB2c/jXb/qd0AR3oDzyDiX+oXoALzWi2Y552aa2W14xyMHr8CdhvfPVp004P+A/nhf0q/jHePm/BGv9ehWP77FeCcjfN5ouavw3pe98d7H451zK/y4VprZNXhFwwN4XcpTWsplOxwE9ATmNJp+unPuITP7MV5O8/Baoi7FOxsXP9ZqM/sF3nG7Bu8zNr6J/UR7XNoqms/F6Xjv8fN4n/t3gYl1rV5RfLa3AkOAp4AeeOPmHscr4kQSlnnjSDsvfzDrC8653f0m7cXOuT4tLP9v4ALn3HsdFaNIKjOzbLwi5jbn3B2N5i0AHnfO3RRIcC3w/7b8B9jHOfdJK4tLG7X0uRBJNZ16zFhj/niH/5jZ/4A3viPymkj+tYwKiThbR0Riy8xGmneh1J3NbCTe9bPygCcjlullZhfjtQb+OZhIpSNF87kQSVWdupvSzP6G18zew8xW4DW9nwzcY2a/wTuVejr/bdY/CZjuOntzoEjiuwQYijdm6XO8a0etiJi/Bm+M07nOufUdH54EpLXPhUhK6vTdlCIiIiKdWVJ1U4qIiIh0NirGRERERALUaceM9ejRww0cODCu+ygrKyM3Nzeu+0hUyj31ck/VvEG5K/fUkqp5Q7C5f/rpp+udcz2bmtdpi7GBAwfyySfxPdt81qxZjB8/Pq77SFTKfXzQYXS4VM0blLtyTy2pmjcEm7uZfdPcPHVTioiIiARIxZiIiIhIgFSMiYiIiARIxZiIiIhIgFSMiYiIiARIxZiIiIhIgFSMiYiIiARIxZiIiIhIgFSMiYiIiAQoYYoxM5toZovN7CszuyroeEREREQ6QkIUY2aWDvwJOALYDTjJzHYLNioRERGR+EuUe1OOAb5yzi0FMLPpwCRgQVAB3fLr+/h06SIeefh1cjYYoRILKpRAFBcXM7PgzaDDCESq5t5U3gef9AOOOufQgCISEUkN5pwLOgbMbDIw0Tl3lv/6VGCsc+7CRsudA5wDUFRUNGr69Olxi+mBN99kyX5VAKRVOIbcsY3MkuCPVUepqakhPT096DACkaq5N8772zmrANhxRN+gQuowqfqeg3JPxdxTNW9oPveiwT047MID4rrvCRMmfOqcG93UvERpGWuq2el7lY9z7j7gPoDRo0e7eN55fff9RvHiu6/TfUh/rp/3DCdNP40j+o6M2/4STZB3tg9aqubeOO8X73uVN/72TnABdaDi4mIKCgqCDiMQyr0g6DA6XKrmDc3n3q9fv0D/7idKMbYC6B/xuh+wKqBYAOiRnceAtAL27bMH1897hjXbNgcZjkiHO+qcQ1OmizJVC3BQ7qmYe6rmDYmbe0IM4Ac+BnYxs53MLAv4CfB8wDEBEErPIj+zC2vKVYyJiIhI7CVEy5hzrtrMLgReBtKBB51z8wMOq16P7DzWV5QEHYaIiIgkoYQoxgCccy8BLwUdR1PCmSFKq8uDDkNERESSUKJ0Uya0cEaIMhVjIiIiEgcqxqIQzlDLmIiIiMSHirEo5GWGKK1SMSYiIiKxp2IsCuGMECXV5STCBXJFREQkuagYi0JuRogaV0tFbVXQoYiIiEiSUTEWhXBGCEBdlSIiIhJzKsaiUF+MaRC/iIiIxJiKsSjkZXrFWImKMREREYkxFWNRUDeliIiIxIuKsSjkqptSRERE4kTLine truncated
|
||||
"text/plain": [
|
||||
"<Figure size 720x432 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"gs = gridspec.GridSpec(nrows=1, ncols=1, width_ratios=[1], height_ratios=[1])\n",
|
||||
"fig = plt.figure(figsize=(10, 6))\n",
|
||||
"\n",
|
||||
"axTmp = plt.subplot(gs[0, 0])\n",
|
||||
"axTmp.plot(times_GD[:idx_stop_GD+1], energy_GD[:idx_stop_GD+1], c=colors[0], \n",
|
||||
" label=\"Gradient Descent ({:}its)\".format(idx_stop_GD))\n",
|
||||
"axTmp.plot(times_BFGS[:idx_stop_BFGS+1], energy_BFGS[:idx_stop_BFGS+1], c=colors[2], \n",
|
||||
" label=\"BFGS ({:}its)\".format(idx_stop_BFGS))\n",
|
||||
"y_lim = axTmp.get_ylim()\n",
|
||||
"axTmp.set_title(\"Total energy as optimization goes\", fontsize=14)\n",
|
||||
"axTmp.set_xlabel(\"Computation time [s]\", fontsize=12)\n",
|
||||
"axTmp.set_ylabel(\"Energy [J]\", fontsize=12)\n",
|
||||
"axTmp.set_ylim(y_lim)\n",
|
||||
"plt.legend(fontsize=12)\n",
|
||||
"plt.grid()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.7"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": true,
|
||||
"sideBar": true,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": true,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Description\n",
|
||||
"\n",
|
||||
"This notebook intends to gather all the functionalities you'll have to implement for assignment 2.2.\n",
|
||||
"\n",
|
||||
"# Load libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import igl\n",
|
||||
"import meshplot as mp\n",
|
||||
"import time\n",
|
||||
"\n",
|
||||
"import sys as _sys\n",
|
||||
"_sys.path.append(\"../src\")\n",
|
||||
"from elasticsolid import *\n",
|
||||
"from elasticenergy import *\n",
|
||||
"from matplotlib import gridspec\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"shadingOptions = {\n",
|
||||
" \"flat\":True,\n",
|
||||
" \"wireframe\":False, \n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"rot = np.array(\n",
|
||||
" [[1, 0, 0 ],\n",
|
||||
" [0, 0, 1],\n",
|
||||
" [0, -1, 0 ]]\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Load mesh\n",
|
||||
"\n",
|
||||
"Several meshes are available for you to play with under `data/`: `ball.obj`, `dinosaur.obj`, and `beam.obj`. You can also uncomment the few commented lines below to manipulate a simple mesh made out of 2 tetrahedra."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"v, _, _, t, _, _ = igl.read_obj(\"../data/beam.obj\")\n",
|
||||
"aabb = np.max(v, axis=0) - np.min(v, axis=0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Linear/Non-Linear Elastic Solid\n",
|
||||
"\n",
|
||||
"## Instantiation\n",
|
||||
"\n",
|
||||
"We first specify the elasticity model to use for the elastic solid, as well as pinned vertices, and volumetric forces."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"rho = 131 # [kg.m-3]\n",
|
||||
"young = 10e6 # [Pa] \n",
|
||||
"poisson = 0.2\n",
|
||||
"force_mass = np.zeros(shape = (3,))\n",
|
||||
"force_mass[2] = - rho * 9.81\n",
|
||||
"\n",
|
||||
"minX = np.min(v[:, 0])\n",
|
||||
"pin_idx = np.arange(v.shape[0])[v[:, 0] < minX + 0.2*aabb[0]]\n",
|
||||
"\n",
|
||||
"ee = LinearElasticEnergy(young, poisson)\n",
|
||||
"neo_ee = NeoHookeanElasticEnergy(young, poisson)\n",
|
||||
"solid = ElasticSolid(v, t, ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)\n",
|
||||
"neo_solid = ElasticSolid(v, t, neo_ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Validate Elastic Energy Gradient (Elastic Forces) using Finite Differences on Elastic Energy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 432x288 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 432x288 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"fd_validation_elastic(solid)\n",
|
||||
"fd_validation_elastic(neo_solid)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Validate External Energy Gradient (External Forces) using Finite Differences on External Energy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 432x288 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 432x288 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"fd_validation_ext(solid)\n",
|
||||
"fd_validation_ext(neo_solid)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.7"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": true,
|
||||
"sideBar": true,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": true,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
import numpy as np
|
||||
import time
|
||||
import math
|
||||
|
||||
def conjugate_gradient(L_method, b):
|
||||
'''
|
||||
Finds an inexact Newton descent direction using Conjugate Gradient (CG)
|
||||
Solves partially L(x) = b where A is positive definite, using CG.
|
||||
The method should be take care of checking whether the added direction is
|
||||
an ascent direction or not, and whether the residuals are small enough.
|
||||
Details can be found in the handout.
|
||||
|
||||
Input:
|
||||
- L_method : a method that computes the Hessian vector product. It should
|
||||
take an array of shape (n,) and return an array of shape (n,)
|
||||
- b : right hand side of the linear system (n,)
|
||||
|
||||
Output:
|
||||
- p_star : np array of shape (n,) solving the linear system approximately
|
||||
'''
|
||||
N = b.shape[0]
|
||||
fshape = (3*N,N)
|
||||
z = np.zeros(fshape)
|
||||
r = np.zeros(fshape)
|
||||
d = np.zeros(fshape)
|
||||
alpha = np.zeros(3*N)
|
||||
beta = np.zeros(3*N)
|
||||
r[0] = -b
|
||||
d[0] = -r[0]
|
||||
ck = 0
|
||||
for k in range(0,3*N):
|
||||
|
||||
if (d[k].T @ L_method(d[k]) <= 0).all():
|
||||
if (k==0):
|
||||
return b
|
||||
else:
|
||||
return z[k]
|
||||
alpha[k] = (r[k].T @ r[k])/(d[k].T @ L_method(d[k]))
|
||||
z[k+1] = z[k] + alpha[k]*d[k]
|
||||
r[k+1] = r[k] + alpha[k]*L_method(d[k])
|
||||
if (np.linalg.norm(r[k+1]) < min(0.5,math.sqrt(np.linalg.norm(b)))*math.sqrt(np.linalg.norm(b) )):
|
||||
break
|
||||
|
||||
beta[k+1] = (r[k].T @ r[k+1])/(r[k].T @ r[k])
|
||||
d[k+1] = -r[k+1] + beta[k+1]*d[k]
|
||||
ck = k
|
||||
|
||||
return z[ck+1]
|
||||
|
||||
|
||||
def compute_inverse_approximate_hessian_matrix(sk, yk, invB_prev):
|
||||
'''
|
||||
Input:
|
||||
- sk : previous step x_{k+1} - x_k, shape (n, 1)
|
||||
- yk : grad(f)_{k+1} - grad(f)_{k}, shape (n, 1)
|
||||
- invB_prev : previous Hessian estimate Bk, shape (n, n)
|
||||
|
||||
Output:
|
||||
- invB_new : previous Hessian estimate Bk, shape (n, n)
|
||||
'''
|
||||
invB_new = invB_prev.copy()
|
||||
invB_new += (sk.T @ yk + yk.T @ invB_prev @ yk) / ((sk.T @ yk) ** 2) * (sk @ sk.T)
|
||||
prod = (invB_prev @ yk) @ sk.T
|
||||
invB_new -= (prod + prod.T) / (sk.T @ yk)
|
||||
return invB_new
|
||||
|
||||
def evaluate_armijo_rule(f_x, f_x1, p, grad, c, alpha):
|
||||
"""
|
||||
Check the armijo rule, return true if the armijo condition is satisfied
|
||||
|
||||
Input:
|
||||
- f_x : float
|
||||
The function value at x
|
||||
- f_x1 : float
|
||||
The function value at x_(k+1) = x_k + alpha * p_k
|
||||
- p: np.array(2 * #V, 1)
|
||||
The flatten search direction
|
||||
Here, we use the flatten the search direction.
|
||||
The flatten process asks the all x coordinates to be first
|
||||
then all y cooridnates to be the second.
|
||||
- grad: np.array(2 * #V, 1)
|
||||
The gradient of the function at x
|
||||
Here, we use the flatten the gradient
|
||||
The flatten process asks the all x coordinates to be first
|
||||
then all y cooridnates to be the second.
|
||||
- c: float
|
||||
The coefficient for armijo condition
|
||||
- alpha: float
|
||||
The current step size
|
||||
|
||||
Output:
|
||||
- condition: bool
|
||||
True if the armijio condition is satisfied
|
||||
"""
|
||||
return f_x1 <= f_x + c*alpha*np.dot(p,grad)
|
||||
|
||||
def equilibrium_convergence_report_GD(solid, v_init, n_steps, step_size, thresh=1e-3):
|
||||
'''
|
||||
Finds the equilibrium by minimizing the total energy using gradient descent.
|
||||
|
||||
Input:
|
||||
- solid : an elastic solid to optimize
|
||||
- v_init : the initial guess for the equilibrium position
|
||||
- n_step : number of optimization steps
|
||||
- step_size : scaling factor of the gradient when taking the step
|
||||
- thresh : threshold to stop the optimization process on the gradient's magnitude
|
||||
|
||||
Ouput:
|
||||
- report : a dictionary containing various quantities of interest
|
||||
'''
|
||||
|
||||
solid.update_def_shape(v_init)
|
||||
|
||||
energies_el = np.zeros(shape=(n_steps+1,))
|
||||
energies_ext = np.zeros(shape=(n_steps+1,))
|
||||
residuals = np.zeros(shape=(n_steps+1,))
|
||||
times = np.zeros(shape=(n_steps+1,))
|
||||
step_sizes = np.zeros(shape=(n_steps,))
|
||||
|
||||
energies_el[0] = solid.energy_el
|
||||
energies_ext[0] = solid.energy_ext
|
||||
residuals[0] = np.linalg.norm((solid.f + solid.f_ext)[solid.free_idx, :])
|
||||
idx_stop = n_steps
|
||||
|
||||
energy_tot_prev = energies_el[0] + energies_ext[0]
|
||||
|
||||
t_start = time.time()
|
||||
for i in range(n_steps):
|
||||
## TODO: Find the descent direction
|
||||
## descent_dir has shape (#v, 3)
|
||||
descent_dir = (solid.f + solid.f_ext)
|
||||
|
||||
|
||||
step_size_tmp = step_size
|
||||
max_l_iter = 20
|
||||
for l_iter in range(max_l_iter):
|
||||
step_size_tmp *= 0.5
|
||||
solid.displace(step_size_tmp * descent_dir)
|
||||
|
||||
## TODO: Check if the armijo rule is satisfied
|
||||
## energy_tot_tmp is the current total energy
|
||||
## armijo is a boolean that says whether the condition is satisfied
|
||||
energy_tot_tmp = solid.energy_ext + solid.energy_el
|
||||
grad_tmp = -descent_dir
|
||||
armijo = energy_tot_tmp < energy_tot_prev + thresh * step_size_tmp * ((descent_dir*grad_tmp).sum())
|
||||
|
||||
if armijo or l_iter == max_l_iter-1:
|
||||
break
|
||||
else:
|
||||
solid.displace(-step_size_tmp * descent_dir)
|
||||
step_sizes[i] = step_size_tmp
|
||||
|
||||
# Measure the force residuals
|
||||
energies_el[i+1] = solid.energy_el
|
||||
energies_ext[i+1] = solid.energy_ext
|
||||
residuals[i+1] = np.linalg.norm((solid.f + solid.f_ext)[solid.free_idx, :])
|
||||
energy_tot_prev = energy_tot_tmp
|
||||
|
||||
if residuals[i+1] < thresh:
|
||||
energies_el[i+1:] = energies_el[i+1]
|
||||
energies_ext[i+1:] = energies_ext[i+1]
|
||||
residuals[i+1:] = residuals[i+1]
|
||||
idx_stop = i
|
||||
break
|
||||
|
||||
times[i+1] = time.time() - t_start
|
||||
|
||||
report = {}
|
||||
report['energies_el'] = energies_el
|
||||
report['energies_ext'] = energies_ext
|
||||
report['residuals'] = residuals
|
||||
report['times'] = times
|
||||
report['idx_stop'] = idx_stop
|
||||
report['step_sizes'] = step_sizes
|
||||
|
||||
return report
|
||||
|
||||
|
||||
def equilibrium_convergence_report_BFGS(solid, v_init, n_steps, step_size, thresh=1e-3):
|
||||
'''
|
||||
Finds the equilibrium by minimizing the total energy using BFGS.
|
||||
|
||||
Input:
|
||||
- solid : an elastic solid to optimize
|
||||
- v_init : the initial guess for the equilibrium position
|
||||
- n_step : number of optimization steps
|
||||
- step_size : scaling factor of the direction when taking the step
|
||||
- thresh : threshold to stop the optimization process on the gradient's magnitude
|
||||
|
||||
Ouput:
|
||||
- report : a dictionary containing various quantities of interest
|
||||
'''
|
||||
|
||||
solid.update_def_shape(v_init)
|
||||
|
||||
energies_el = np.zeros(shape=(n_steps+1,))
|
||||
energies_ext = np.zeros(shape=(n_steps+1,))
|
||||
residuals = np.zeros(shape=(n_steps+1,))
|
||||
times = np.zeros(shape=(n_steps+1,))
|
||||
energies_el[0] = solid.energy_el
|
||||
energies_ext[0] = solid.energy_ext
|
||||
## TODO: Collect free vertex positions
|
||||
## grad_tmp is the current flattened gradient of the total energy
|
||||
## with respect to the free vertices
|
||||
grad_tmp = - (solid.f + solid.f_ext)[solid.free_idx,:].reshape(-1,1)
|
||||
residuals[0] = np.linalg.norm(grad_tmp)
|
||||
idx_stop = n_steps
|
||||
|
||||
energy_tot_prev = energies_el[0] + energies_ext[0]
|
||||
|
||||
|
||||
## TODO: Collect free vertex positions
|
||||
## v_tmp are the current flattened free vertices
|
||||
v_tmp = solid.v_def[solid.free_idx,:].reshape(-1,1)
|
||||
dir_zeros = np.zeros_like(solid.v_def)
|
||||
invB_prev = np.eye(v_tmp.shape[0])
|
||||
|
||||
t_start = time.time()
|
||||
for i in range(n_steps):
|
||||
|
||||
dir_tmp = - invB_prev @ grad_tmp
|
||||
dir_zeros[solid.free_idx, :] = dir_tmp.reshape(-1, 3)
|
||||
|
||||
step_size_tmp = step_size
|
||||
max_l_iter = 20
|
||||
for l_iter in range(max_l_iter):
|
||||
step_size_tmp *= 0.5
|
||||
solid.displace(step_size_tmp * dir_zeros)
|
||||
|
||||
## TODO: Check if the armijo rule is satisfied
|
||||
## energy_tot_tmp is the current total energy
|
||||
## armijo is a boolean that says whether the condition is satisfied
|
||||
energy_tot_tmp = solid.energy_el + solid.energy_ext
|
||||
armijo = energy_tot_tmp < energy_tot_prev + thresh * step_size_tmp*((dir_tmp*grad_tmp).sum())
|
||||
|
||||
if armijo or l_iter == max_l_iter-1:
|
||||
break
|
||||
else:
|
||||
solid.displace(-step_size_tmp * dir_zeros)
|
||||
|
||||
## TODO: Update all quantities
|
||||
## v_new are the new flattened free vertices
|
||||
## grad_new is the new flattened gradient of the total energy
|
||||
## with respect to the free vertices
|
||||
v_new = solid.v_def[solid.free_idx,:].reshape(-1,1)
|
||||
grad_new = - (solid.f+solid.f_ext)[solid.free_idx,:].reshape(-1,1)
|
||||
invB_prev = compute_inverse_approximate_hessian_matrix(v_new - v_tmp,
|
||||
grad_new - grad_tmp,
|
||||
invB_prev)
|
||||
v_tmp = v_new.copy()
|
||||
grad_tmp = grad_new.copy()
|
||||
|
||||
energies_el[i+1] = solid.energy_el
|
||||
energies_ext[i+1] = solid.energy_ext
|
||||
residuals[i+1] = np.linalg.norm(grad_tmp)
|
||||
|
||||
if residuals[i+1] < thresh:
|
||||
residuals[i+1:] = residuals[i+1]
|
||||
energies_el[i+1:] = energies_el[i+1]
|
||||
energies_ext[i+1:] = energies_ext[i+1]
|
||||
idx_stop = i
|
||||
break
|
||||
|
||||
times[i+1] = time.time() - t_start
|
||||
|
||||
report = {}
|
||||
report['energies_el'] = energies_el
|
||||
report['energies_ext'] = energies_ext
|
||||
report['residuals'] = residuals
|
||||
report['times'] = times
|
||||
report['idx_stop'] = idx_stop
|
||||
|
||||
return report
|
||||
|
||||
def equilibrium_convergence_report_NCG(solid, v_init, n_steps, thresh=1e-3):
|
||||
'''
|
||||
Finds the equilibrium by minimizing the total energy using Newton CG.
|
||||
|
||||
Input:
|
||||
- solid : an elastic solid to optimize
|
||||
- v_init : the initial guess for the equilibrium position
|
||||
- n_step : number of optimization steps
|
||||
- thresh : threshold to stop the optimization process on the gradient's magnitude
|
||||
|
||||
Ouput:
|
||||
- report : a dictionary containing various quantities of interest
|
||||
'''
|
||||
|
||||
solid.update_def_shape(v_init)
|
||||
|
||||
energies_el = np.zeros(shape=(n_steps+1,))
|
||||
energies_ext = np.zeros(shape=(n_steps+1,))
|
||||
residuals = np.zeros(shape=(n_steps+1,))
|
||||
times = np.zeros(shape=(n_steps+1,))
|
||||
energies_el[0] = solid.energy_el
|
||||
energies_ext[0] = solid.energy_ext
|
||||
residuals[0] = np.linalg.norm((solid.f + solid.f_ext)[solid.free_idx, :])
|
||||
idx_stop = n_steps
|
||||
|
||||
t_start = time.time()
|
||||
for i in range(n_steps):
|
||||
# Take a Newton step
|
||||
solid.equilibrium_step()
|
||||
|
||||
# Measure the force residuals
|
||||
energies_el[i+1] = solid.energy_el
|
||||
energies_ext[i+1] = solid.energy_ext
|
||||
residuals[i+1] = np.linalg.norm((solid.f + solid.f_ext)[solid.free_idx, :])
|
||||
|
||||
if residuals[i+1] < thresh:
|
||||
residuals[i+1:] = residuals[i+1]
|
||||
energies_el[i+1:] = energies_el[i+1]
|
||||
energies_ext[i+1:] = energies_ext[i+1]
|
||||
idx_stop = i
|
||||
break
|
||||
|
||||
times[i+1] = time.time() - t_start
|
||||
|
||||
report = {}
|
||||
report['energies_el'] = energies_el
|
||||
report['energies_ext'] = energies_ext
|
||||
report['residuals'] = residuals
|
||||
report['times'] = times
|
||||
report['idx_stop'] = idx_stop
|
||||
|
||||
return report
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
def fd_validation_ext(solid):
|
||||
epsilons = np.logspace(-9,-3,100)
|
||||
perturb_global = np.random.uniform(-1e-3, 1e-3, size=solid.v_def.shape)
|
||||
solid.displace(perturb_global)
|
||||
v_def = solid.v_def.copy()
|
||||
perturb = np.random.uniform(-1, 1, size=solid.v_def.shape)
|
||||
errors = []
|
||||
for eps in epsilons:
|
||||
# Back to original
|
||||
solid.update_def_shape(v_def)
|
||||
grad = np.zeros(solid.f_ext.shape)
|
||||
grad[solid.free_idx] = -solid.f_ext.copy()[solid.free_idx]
|
||||
an_delta_E = (grad*perturb).sum()
|
||||
|
||||
# One step forward
|
||||
solid.displace(perturb * eps)
|
||||
E1 = solid.energy_ext.copy()
|
||||
|
||||
# Two steps backward
|
||||
solid.displace(-2*perturb * eps)
|
||||
E2 = solid.energy_ext.copy()
|
||||
|
||||
# Compute error
|
||||
fd_delta_E = (E1 - E2)/(2*eps)
|
||||
errors.append(abs(fd_delta_E - an_delta_E)/abs(an_delta_E))
|
||||
plt.loglog(epsilons, errors)
|
||||
plt.grid()
|
||||
plt.show()
|
||||
|
||||
def fd_validation_elastic(solid):
|
||||
epsilons = np.logspace(-9,-3,100)
|
||||
perturb_global = np.random.uniform(-1e-3, 1e-3, size=solid.v_def.shape)
|
||||
solid.displace(perturb_global)
|
||||
|
||||
v_def = solid.v_def.copy()
|
||||
solid.make_elastic_forces()
|
||||
|
||||
perturb = np.random.uniform(-1, 1, size=solid.v_def.shape)
|
||||
errors = []
|
||||
for eps in epsilons:
|
||||
# Back to original
|
||||
solid.update_def_shape(v_def)
|
||||
solid.make_elastic_forces()
|
||||
grad = np.zeros(solid.f.shape)
|
||||
grad[solid.free_idx] = -solid.f.copy()[solid.free_idx]
|
||||
an_delta_E = (grad*perturb).sum()
|
||||
|
||||
# One step forward
|
||||
solid.displace(perturb * eps)
|
||||
E1 = solid.energy_el.copy()
|
||||
|
||||
# Two steps backward
|
||||
solid.displace(-2*perturb * eps)
|
||||
E2 = solid.energy_el.copy()
|
||||
|
||||
# Compute error
|
||||
fd_delta_E = (E1 - E2)/(2*eps)
|
||||
errors.append(abs(fd_delta_E - an_delta_E)/abs(an_delta_E))
|
||||
solid.displace(perturb * eps)
|
||||
|
||||
plt.loglog(epsilons, errors)
|
||||
plt.grid()
|
||||
plt.show()
|
||||
|
||||
def fd_validation_elastic_differentials(solid):
|
||||
epsilons = np.logspace(-9, 3,500)
|
||||
perturb_global = 1e-3*np.random.uniform(-1., 1., size=solid.v_def.shape)
|
||||
solid.displace(perturb_global)
|
||||
|
||||
v_def = solid.v_def.copy()
|
||||
|
||||
perturb = np.random.uniform(-1, 1, size=solid.v_def.shape)
|
||||
errors = []
|
||||
for eps in epsilons:
|
||||
# Back to original
|
||||
solid.update_def_shape(v_def)
|
||||
perturb_0s = np.zeros_like(perturb)
|
||||
perturb_0s[solid.free_idx] = perturb[solid.free_idx]
|
||||
an_df = solid.compute_force_differentials(perturb_0s)[solid.free_idx, :]
|
||||
an_df_full = np.zeros(solid.f.shape)
|
||||
an_df_full[solid.free_idx] = an_df.copy()
|
||||
|
||||
# One step forward
|
||||
solid.displace(perturb * eps)
|
||||
f1 = solid.f[solid.free_idx, :]
|
||||
f1_full = np.zeros(solid.f.shape)
|
||||
f1_full[solid.free_idx] = f1
|
||||
|
||||
# Two steps backward
|
||||
solid.displace(-2*perturb * eps)
|
||||
f2 = solid.f[solid.free_idx, :]
|
||||
f2_full = np.zeros(solid.f.shape)
|
||||
f2_full[solid.free_idx] = f2
|
||||
|
||||
# Compute error
|
||||
fd_delta_f = (f1_full - f2_full)/(2*eps)
|
||||
norm_an_df = np.linalg.norm(an_df_full)
|
||||
norm_error = np.linalg.norm(an_df_full - fd_delta_f)
|
||||
errors.append(norm_error/norm_an_df)
|
||||
|
||||
plt.loglog(epsilons, errors)
|
||||
plt.grid()
|
||||
plt.show()
|
||||
@@ -0,0 +1,163 @@
|
||||
import numpy as np
|
||||
from numpy.core.einsumfunc import einsum
|
||||
from numpy.core.fromnumeric import swapaxes
|
||||
|
||||
class ElasticEnergy:
|
||||
def __init__(self, young, poisson):
|
||||
'''
|
||||
Input:
|
||||
- young : Young's modulus [Pa]
|
||||
- poisson : Poisson ratio
|
||||
'''
|
||||
self.young = young
|
||||
self.poisson = poisson
|
||||
self.lbda = young * poisson / ((1 + poisson) * (1 - 2 * poisson))
|
||||
self.mu = young / (2 * (1 + poisson))
|
||||
|
||||
self.psi = None
|
||||
self.E = None
|
||||
self.P = None
|
||||
|
||||
self.dE = None
|
||||
self.dP = None
|
||||
|
||||
def make_energy_density(self, jac):
|
||||
'''
|
||||
This method computes the energy density at each tetrahedron (#t,),
|
||||
and stores the result in self.psi
|
||||
|
||||
Input:
|
||||
- jac : jacobian of the deformation (#t, 3, 3)
|
||||
|
||||
Updated attributes:
|
||||
- psi : energy density per tet (#t,)
|
||||
'''
|
||||
|
||||
print("Please specify the kind of elasticity model.")
|
||||
raise NotImplementedError
|
||||
|
||||
def make_strain_tensor(self, jac):
|
||||
'''
|
||||
This method computes the strain tensor (#t, 3, 3), and stores it in self.E
|
||||
|
||||
Input:
|
||||
- jac : jacobian of the deformation (#t, 3, 3)
|
||||
|
||||
Updated attributes:
|
||||
- E : strain induced by the deformation (#t, 3, 3)
|
||||
'''
|
||||
|
||||
print("Please specify the kind of elasticity model.")
|
||||
raise NotImplementedError
|
||||
|
||||
def make_piola_kirchhoff_stress_tensor(self, jac):
|
||||
'''
|
||||
This method computes the stress tensor (#t, 3, 3), and stores it in self.P
|
||||
|
||||
Input:
|
||||
- jac : jacobian of the deformation (#t, 3, 3)
|
||||
|
||||
Updated attributes:
|
||||
- P : stress tensor induced by the deformation (#t, 3, 3)
|
||||
'''
|
||||
|
||||
print("Please specify the kind of elasticity model.")
|
||||
raise NotImplementedError
|
||||
|
||||
def make_differential_strain_tensor(self, jac, dJac):
|
||||
'''
|
||||
This method computes the differential of strain tensor (#t, 3, 3),
|
||||
and stores it in self.dE
|
||||
|
||||
Input:
|
||||
- jac : jacobian of the deformation (#t, 3, 3)
|
||||
- dJac : differential of the jacobian of the deformation (#t, 3, 3)
|
||||
|
||||
Updated attributes:
|
||||
- dE : differential of the strain tensor (#t, 3, 3)
|
||||
'''
|
||||
|
||||
print("Please specify the kind of elasticity model.")
|
||||
raise NotImplementedError
|
||||
|
||||
def make_differential_piola_kirchhoff_stress_tensor(self, jac, dJac):
|
||||
'''
|
||||
This method computes the differential of the stress tensor (#t, 3, 3), and stores it in self.dP
|
||||
|
||||
Input:
|
||||
- jac : jacobian of the deformation (#t, 3, 3)
|
||||
- dJac : differential of the jacobian of the deformation (#t, 3, 3)
|
||||
|
||||
Updated attributes:
|
||||
- dP : differential of the stress tensor (#t, 3, 3)
|
||||
'''
|
||||
|
||||
print("Please specify the kind of elasticity model.")
|
||||
raise NotImplementedError
|
||||
|
||||
class LinearElasticEnergy(ElasticEnergy):
|
||||
def __init__(self, young, poisson):
|
||||
super().__init__(young, poisson)
|
||||
|
||||
def make_energy_density(self, jac):
|
||||
fa = self.mu * np.einsum("ijk,ijk->i",self.E, self.E)
|
||||
fb = self.lbda/2.0 * np.einsum('ijj->i' ,self.E)**2
|
||||
self.psi = fa + fb
|
||||
|
||||
def make_strain_tensor(self, jac):
|
||||
self.E = (jac+np.transpose(jac,axes=(0,2,1)))/2.0 - np.identity(3)
|
||||
|
||||
def make_piola_kirchhoff_stress_tensor(self, jac):
|
||||
fa = 2.0*self.mu*self.E
|
||||
fb = self.lbda* np.einsum('i,jk->ijk',np.einsum('ijj->i',self.E), np.identity(3))
|
||||
self.P = fa + fb
|
||||
|
||||
def make_differential_strain_tensor(self, jac, dJac):
|
||||
self.dE = (dJac+np.transpose(dJac,axes=(0,2,1)))/2.0
|
||||
|
||||
def make_differential_piola_kirchhoff_stress_tensor(self, jac, dJac):
|
||||
fa = 2.0*self.mu*self.dE
|
||||
fb = self.lbda* np.einsum("i,jk->ijk",np.trace(self.dE, axis1=1,axis2=2), np.identity(3))
|
||||
self.dP = fa + fb
|
||||
|
||||
class NeoHookeanElasticEnergy(ElasticEnergy):
|
||||
def __init__(self, young, poisson):
|
||||
super().__init__(young, poisson)
|
||||
self.logJ = None
|
||||
self.Finv = None
|
||||
|
||||
def make_energy_density(self, jac):
|
||||
i1 = np.einsum('ijk,ijk->i',jac,jac)
|
||||
j = np.log(np.linalg.det(jac))
|
||||
fa = self.mu/2.0 * (i1-3 - 2*j)
|
||||
fb = self.lbda/2.0 * j**2
|
||||
self.psi = fa + fb
|
||||
|
||||
def make_strain_tensor(self, jac):
|
||||
pass
|
||||
|
||||
def make_piola_kirchhoff_stress_tensor(self, jac):
|
||||
'''
|
||||
Additional updated attributes:
|
||||
- logJ ; log of the determinant of the jacobians (#t,)
|
||||
- Finv : inverse of the jacobians (#t, 3, 3)
|
||||
'''
|
||||
self.logJ = np.log(np.linalg.det(jac))
|
||||
self.Finv = np.linalg.inv(jac)
|
||||
FinvT = np.transpose(self.Finv,axes=(0,2,1))
|
||||
fa = self.mu * (jac - FinvT)
|
||||
fb = self.lbda * np.einsum("i,ijk->ijk",self.logJ, FinvT)
|
||||
self.P = fa +fb
|
||||
|
||||
def make_differential_strain_tensor(self, jac, dJac):
|
||||
pass
|
||||
|
||||
def make_differential_piola_kirchhoff_stress_tensor(self, jac, dJac):
|
||||
self.logJ = np.log(np.linalg.det(jac))
|
||||
self.Finv = np.linalg.inv(jac)
|
||||
FinvT = np.transpose(self.Finv,axes=(0,2,1))
|
||||
dFT = np.transpose(dJac,axes=(0,2,1))
|
||||
fa = self.mu * dJac
|
||||
fb = np.einsum("i,ijk->ijk",(self.mu - self.lbda * self.logJ),FinvT @ dFT @ FinvT)
|
||||
fc = self.lbda * np.einsum("i,ijk->ijk",np.trace(self.Finv @ dJac, axis1=1,axis2=2),FinvT)
|
||||
self.dP = fa + fb + fc
|
||||
@@ -0,0 +1,404 @@
|
||||
import numpy as np
|
||||
from numpy import linalg
|
||||
from scipy import sparse
|
||||
from Utils import *
|
||||
import igl
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
# ELASTIC SOLID CLASS
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class ElasticSolid(object):
|
||||
|
||||
def __init__(self, v_rest, t, ee, rho=1, pin_idx=[], f_mass=None):
|
||||
'''
|
||||
Input:
|
||||
- v_rest : position of the vertices of the mesh (#v, 3)
|
||||
- t : indices of the element's vertices (#t, 4)
|
||||
- ee : elastic energy object that can be found in elasticenergy.py
|
||||
- rho : mass per unit volume [kg.m-3]
|
||||
- pin_idx : list or np array of vertex indices to pin
|
||||
- f_mass : external force per unit mass (3,) [N.kg-1]
|
||||
'''
|
||||
|
||||
self.v_rest = v_rest.copy()
|
||||
self.v_def = v_rest.copy()
|
||||
self.t = t
|
||||
self.ee = ee
|
||||
self.rho = rho
|
||||
self.pin_idx = np.array(pin_idx)
|
||||
self.f_mass = f_mass.copy()
|
||||
self.free_idx = None
|
||||
self.pin_mask = None
|
||||
|
||||
self.W0 = None
|
||||
self.Dm = None
|
||||
self.Bm = None
|
||||
self.rest_barycenters = None
|
||||
|
||||
self.W = None
|
||||
self.Ds = None
|
||||
self.F = None
|
||||
self.def_barycenters = None
|
||||
|
||||
self.energy_el = None
|
||||
self.energy_ext = None
|
||||
|
||||
self.f = None
|
||||
self.f_vol = None
|
||||
self.f_ext = None
|
||||
|
||||
self.make_free_indices_and_pin_mask()
|
||||
self.update_rest_shape(self.v_rest)
|
||||
self.update_def_shape(self.v_def)
|
||||
|
||||
## Utils ##
|
||||
|
||||
def vertex_tet_sum(self, data):
|
||||
'''
|
||||
Distributes data specified at each tetrahedron to the neighboring vertices.
|
||||
All neighboring vertices will receive the value indicated at the corresponding tet position in data.
|
||||
|
||||
Input:
|
||||
- data : np array of shape (#t,) or (4*#t,)
|
||||
|
||||
Output:
|
||||
- data_sum : np array of shape (#v,), containing the summed data
|
||||
'''
|
||||
i = self.t.flatten('F') # (4*#t,)
|
||||
j = np.arange(len(self.t)) # (#t,)
|
||||
j = np.tile(j, 4) # (4*#t,)
|
||||
|
||||
if len(data) == len(self.t):
|
||||
data = data[j]
|
||||
|
||||
# Has shape (#v, #t)
|
||||
m = sparse.coo_matrix((data, (i, j)), (len(self.v_rest), len(self.t)))
|
||||
return np.array(m.sum(axis=1)).flatten()
|
||||
|
||||
## Precomputation ##
|
||||
|
||||
def make_free_indices_and_pin_mask(self):
|
||||
'''
|
||||
Should list all the free indices and the pin mask.
|
||||
|
||||
Updated attributes:
|
||||
- free_index : np array of shape (#free_vertices,) containing the list of unpinned vertices
|
||||
- pin_mask : np array of shape (#v, 1) containing 1 at free vertex indices and 0 at pinned vertex indices
|
||||
'''
|
||||
self.pin_mask = np.ones((self.v_rest.shape[0],1))
|
||||
self.free_idx = np.arange(0,self.v_rest.shape[0])
|
||||
if(self.pin_idx.shape[0]<=0):
|
||||
return
|
||||
self.pin_mask[self.pin_idx] = 0
|
||||
self.free_idx = np.where(self.pin_mask==1)[0]
|
||||
|
||||
|
||||
|
||||
## Methods related to rest quantities ##
|
||||
|
||||
def make_rest_barycenters(self):
|
||||
'''
|
||||
Construct the barycenters of the undeformed configuration
|
||||
|
||||
Updated attributes:
|
||||
- rest_barycenters : np array of shape (#t, 3) containing the position of each tet's barycenter
|
||||
'''
|
||||
self.rest_barycenters = np.einsum("ijk->ik",self.v_rest[self.t])/4
|
||||
|
||||
def make_rest_shape_matrices(self):
|
||||
'''
|
||||
Construct Ds that has shape (#t, 3, 3), and its inverse Bm
|
||||
|
||||
Updated attributes:
|
||||
- Dm : np array of shape (#t, 3, 3) containing the shape matrix of each tet
|
||||
- Bm : np array of shape (#t, 3, 3) containing the inverse shape matrix of each tet
|
||||
'''
|
||||
tv = self.v_rest[self.t]
|
||||
|
||||
tva = tv[:,:3,:]
|
||||
tvb = tv[:,3,:].reshape((self.t.shape[0],1,3))
|
||||
tvb= np.repeat(tvb, 3, axis=1)
|
||||
|
||||
tvs = tva - tvb
|
||||
tvsf = np.transpose(tvs,(0,2,1))
|
||||
|
||||
self.Dm = tvsf
|
||||
self.Bm = np.linalg.inv(tvsf)
|
||||
|
||||
def update_rest_shape(self, v_rest):
|
||||
'''
|
||||
Updates the vertex position, the shape matrices Dm and Bm, the volumes W0,
|
||||
and the mass matrix at rest
|
||||
|
||||
Input:
|
||||
- v_rest : position of the vertices of the mesh at rest state (#v, 3)
|
||||
|
||||
Updated attributes:
|
||||
- v_rest : np array of shape (#v, 3) containing the position of each vertex at rest
|
||||
- W0 : np array of shape (#t,) containing the signed volume of each tet
|
||||
'''
|
||||
self.v_rest = v_rest
|
||||
self.make_rest_barycenters()
|
||||
self.make_rest_shape_matrices()
|
||||
self.W0 = -np.linalg.det(self.Dm)/6
|
||||
self.update_def_shape(self.v_def)
|
||||
self.make_volumetric_and_external_forces()
|
||||
|
||||
## Methods related to deformed quantities ##
|
||||
|
||||
def make_def_barycenters(self):
|
||||
'''
|
||||
Construct the barycenters of the deformed configuration
|
||||
|
||||
Updated attributes:
|
||||
- def_barycenters : np array of shape (#t, 3) containing the position of each tet's barycenter
|
||||
'''
|
||||
self.def_barycenters = np.einsum("ijk->ik",self.v_def[self.t])/4
|
||||
|
||||
def make_def_shape_matrices(self):
|
||||
'''
|
||||
Construct Ds that has shape (#t, 3, 3)
|
||||
|
||||
Updated attributes:
|
||||
- Ds : np array of shape (#t, 3, 3) containing the shape matrix of each tet
|
||||
'''
|
||||
tv = self.v_def[self.t]
|
||||
|
||||
tva = tv[:,:3,:]
|
||||
tvb = tv[:,3,:].reshape((self.t.shape[0],1,3))
|
||||
tvb= np.repeat(tvb, 3, axis=1)
|
||||
|
||||
tvs = tva - tvb
|
||||
tvsf = np.transpose(tvs,(0,2,1))
|
||||
|
||||
self.Ds = tvsf
|
||||
|
||||
def make_jacobians(self):
|
||||
'''
|
||||
Compute the current Jacobian of the deformation
|
||||
|
||||
Updated attributes:
|
||||
- F : np array of shape (#t, 3, 3) containing Jacobian of the deformation in each tet
|
||||
'''
|
||||
self.F = self.Ds @ self.Bm # <=> np.einsum("lij,ljk->lik",self.Ds,self.Bm)
|
||||
|
||||
def update_def_shape(self, v_def):
|
||||
'''
|
||||
Updates the vertex position, the Jacobian of the deformation, and the
|
||||
resulting elastic forces.
|
||||
|
||||
Input:
|
||||
- v_def : position of the vertices of the mesh (#v, 3)
|
||||
|
||||
Updated attributes:
|
||||
- v_def : np array of shape (#v, 3) containing the position of each vertex after deforming the solid
|
||||
- W : np array of shape (#t,) containing the signed volume of each tet
|
||||
'''
|
||||
self.v_def = self.v_rest
|
||||
self.v_def[self.free_idx] = v_def[self.free_idx]
|
||||
self.make_def_barycenters()
|
||||
self.make_def_shape_matrices()
|
||||
self.W = -np.linalg.det(self.Ds)/6
|
||||
self.make_jacobians()
|
||||
if(self.f_vol is None):
|
||||
self.make_volumetric_and_external_forces()
|
||||
self.make_elastic_forces()
|
||||
self.make_elastic_energy()
|
||||
self.make_external_energy()
|
||||
|
||||
def displace(self, v_disp):
|
||||
'''
|
||||
Displace the whole mesh so that v_def += v_disp
|
||||
|
||||
Input:
|
||||
- v_disp : displacement of the vertices of the mesh (#v, 3)
|
||||
'''
|
||||
self.update_def_shape(self.v_def + v_disp)
|
||||
|
||||
## Energies ##
|
||||
|
||||
def make_elastic_energy(self):
|
||||
'''
|
||||
This updates the elastic energy
|
||||
|
||||
Updated attributes:
|
||||
- energy_el : elastic energy of the system [J]
|
||||
'''
|
||||
self.ee.make_strain_tensor(self.F)
|
||||
self.ee.make_energy_density(self.F)
|
||||
self.energy_el = np.sum(self.W0 * self.ee.psi)
|
||||
|
||||
def make_external_energy(self):
|
||||
'''
|
||||
This computes the external energy potential
|
||||
|
||||
Updated attributes:
|
||||
- energy_ext : postential energy due to external forces [J]
|
||||
'''
|
||||
dx = self.def_barycenters - self.rest_barycenters
|
||||
ifv = np.einsum('i,ij -> ij', self.W0, self.f_vol)
|
||||
self.energy_ext = - np.einsum("i,ij,ij->",self.W0, self.f_vol, dx)
|
||||
|
||||
## Forces ##
|
||||
|
||||
def make_elastic_forces(self):
|
||||
'''
|
||||
This method updates the elastic forces stored in self.f (#v, 3)
|
||||
|
||||
Updated attributes:
|
||||
- f : elastic forces per vertex (#v, 3)
|
||||
- ee : elastic energy, some attributes should be updated
|
||||
'''
|
||||
self.ee.make_strain_tensor(self.F)
|
||||
self.ee.make_piola_kirchhoff_stress_tensor(self.F)
|
||||
tdm = np.transpose(self.Bm,(0,2,1))
|
||||
ptdm = self.ee.P @ tdm
|
||||
f123 = -np.einsum("i,ijk->ikj",self.W0,ptdm )
|
||||
f4 = -f123[:,0] - f123[:,1] - f123[:,2]
|
||||
H = np.hstack((f123,f4[:,None]))
|
||||
|
||||
x = self.vertex_tet_sum(H[:,:,0].flatten('F'))
|
||||
y = self.vertex_tet_sum(H[:,:,1].flatten('F'))
|
||||
z = self.vertex_tet_sum(H[:,:,2].flatten('F'))
|
||||
|
||||
self.f = np.hstack((x[:,None],y[:,None],z[:,None]))
|
||||
|
||||
def make_volumetric_and_external_forces(self):
|
||||
'''
|
||||
Convert force per unit mass to volumetric forces, then distribute
|
||||
the forces to the vertices of the mesh.
|
||||
|
||||
Updated attributes:
|
||||
- f_vol : np array of shape (#t, 3) external force per unit volume acting on the tets
|
||||
- f_ext : np array of shape (#v, 3) external force acting on the vertices
|
||||
'''
|
||||
mpv = self.f_mass*self.rho
|
||||
self.f_vol = np.ones((self.W0.shape[0],1)) * mpv
|
||||
|
||||
ifv = np.einsum('i,ij -> ij', self.W0, self.f_vol)
|
||||
|
||||
f_ext_x = self.vertex_tet_sum(ifv[:,0])
|
||||
f_ext_y = self.vertex_tet_sum(ifv[:,1])
|
||||
f_ext_z = self.vertex_tet_sum(ifv[:,2])
|
||||
|
||||
self.f_ext = np.stack((f_ext_x,f_ext_y,f_ext_z),axis=1) / 4.0
|
||||
|
||||
## Force Differentials
|
||||
|
||||
def compute_force_differentials(self, v_disp):
|
||||
'''
|
||||
This computes the differential of the force given a displacement dx,
|
||||
where df = df/dx|x . dx = - K(x).dx. Where K(x) is the stiffness matrix (or Hessian)
|
||||
of the solid. Note that the implementation doesn't need to construct the stiffness matrix explicitly.
|
||||
|
||||
Input:
|
||||
- v_disp : displacement of the vertices of the mesh (#v, 3)
|
||||
|
||||
Output:
|
||||
- df : force differentials at the vertices of the mesh (#v, 3)
|
||||
|
||||
Updated attributes:
|
||||
- ee : elastic energy, some attributes should be updated
|
||||
'''
|
||||
|
||||
# First compute the differential of the Jacobian
|
||||
tv = v_disp[self.t]
|
||||
tva = tv[:,:3,:]
|
||||
tvb = tv[:,3,:].reshape((-1,1,3))
|
||||
|
||||
tvb= np.repeat(tvb, 3, axis=1)
|
||||
|
||||
tvs = tva - tvb
|
||||
tvsf = np.transpose(tvs,(0,2,1))
|
||||
|
||||
dDs = tvsf
|
||||
dF = dDs @ self.Bm
|
||||
|
||||
# Then update differential quantities in self.ee
|
||||
self.ee.make_differential_strain_tensor(self.F,dF)
|
||||
self.ee.make_differential_piola_kirchhoff_stress_tensor(self.F,dF)
|
||||
|
||||
# Compute the differential of the forces
|
||||
tdm = np.transpose(self.Bm,(0,2,1))
|
||||
ptdm = self.ee.dP @ tdm
|
||||
f123 = -np.einsum("i,ijk->ikj",self.W0,ptdm )
|
||||
f4 = -f123[:,0] - f123[:,1] - f123[:,2]
|
||||
H = np.hstack((f123,f4[:,None]))
|
||||
|
||||
x = self.vertex_tet_sum(H[:,:,0].flatten('F'))
|
||||
y = self.vertex_tet_sum(H[:,:,1].flatten('F'))
|
||||
z = self.vertex_tet_sum(H[:,:,2].flatten('F'))
|
||||
|
||||
return np.hstack((x[:,None],y[:,None],z[:,None]))
|
||||
|
||||
def equilibrium_step(self, step_size_init = 2, max_l_iter = 20, c1 = 1e-4):
|
||||
'''
|
||||
This function displaces the whole solid to the next deformed configuration
|
||||
using a Newton-CG step.
|
||||
|
||||
Updated attributes:
|
||||
- LHS : The hessian vector product
|
||||
- RHS : Right hand side for the conjugate gradient linear solve
|
||||
Other than them, only attributes updated by displace(self, v_disp) should be changed
|
||||
'''
|
||||
|
||||
# Define LHS
|
||||
def LHS(dx):
|
||||
'''
|
||||
Should implement the Hessian-Vector Product L(dx), and take care of pinning constraints
|
||||
as described in the handout.
|
||||
'''
|
||||
if len(dx.shape)==1:
|
||||
dx = dx.reshape((-1,3))
|
||||
|
||||
if (dx.shape[0] < self.v_rest.shape[0]):
|
||||
dxf = np.zeros((self.v_rest.shape[0],3))
|
||||
dxf[self.free_idx] = dx
|
||||
dx = dxf
|
||||
|
||||
res = self.compute_force_differentials(dx)
|
||||
|
||||
return res[self.free_idx].flatten()
|
||||
|
||||
self.LHS = LHS # Save to class for testing
|
||||
|
||||
# Define RHS
|
||||
RHS = - (self.f + self.f_ext)[self.free_idx]
|
||||
|
||||
self.RHS = RHS # Save to class for testing
|
||||
|
||||
# Use conjugate gradient to find a descent direction
|
||||
# (see conjugate_gradient in Utils.py)
|
||||
dx_CG = conjugate_gradient(LHS,RHS.flatten()) # shape (#v, 3)
|
||||
|
||||
|
||||
# Run line search on the direction
|
||||
step_size = step_size_init
|
||||
ft = self.f + self.f_ext
|
||||
energy_tot_prev = self.energy_el + self.energy_ext
|
||||
for l_iter in range(max_l_iter):
|
||||
step_size *= 0.5 # DO NOT CHANGE
|
||||
dx_search = dx_CG * step_size
|
||||
self.displace(dx_search)
|
||||
|
||||
# Current force norm for unpinned vertices
|
||||
f_tmp = (self.f + self.f_ext)
|
||||
f_tmp[self.free_idx] = 0
|
||||
g = np.linalg.norm(f_tmp)
|
||||
|
||||
energy_tot_tmp = self.energy_el + self.energy_ext
|
||||
|
||||
#Make sure you only use the gradient of the unpinned vertices
|
||||
# USE parameter c1 = 1e-4 (from the function arguments) when you submit
|
||||
armijo = evaluate_armijo_rule(energy_tot_prev, energy_tot_tmp, dx_CG, -dx_CG, c1, step_size)
|
||||
|
||||
if armijo or l_iter == max_l_iter-1:
|
||||
print("Energy: " + str(energy_tot_tmp) + " Force norm: " + str(g) + " Line search Iters: " + str(l_iter))
|
||||
break
|
||||
else:
|
||||
self.displace(-dx_search)
|
||||
|
After Width: | Height: | Size: 460 KiB |
|
After Width: | Height: | Size: 538 KiB |
|
After Width: | Height: | Size: 532 KiB |
|
After Width: | Height: | Size: 737 KiB |
|
After Width: | Height: | Size: 356 KiB |
|
After Width: | Height: | Size: 324 KiB |
|
After Width: | Height: | Size: 429 KiB |
|
After Width: | Height: | Size: 613 KiB |
|
After Width: | Height: | Size: 343 KiB |
|
After Width: | Height: | Size: 683 KiB |
@@ -0,0 +1,114 @@
|
||||
import time
|
||||
import pytest
|
||||
import json
|
||||
import sys
|
||||
import igl
|
||||
import numpy as np
|
||||
sys.path.append('../')
|
||||
sys.path.append('../src')
|
||||
from elasticsolid import *
|
||||
from elasticenergy import *
|
||||
eps = 1E-6
|
||||
|
||||
with open('test_data2.json', 'r') as infile:
|
||||
homework_datas = json.load(infile)
|
||||
|
||||
@pytest.mark.timeout(0.5)
|
||||
@pytest.mark.parametrize("data", homework_datas[0])
|
||||
def test_linear_psi(data):
|
||||
young, poisson, F, psi_gt = data
|
||||
ee = LinearElasticEnergy(young, poisson)
|
||||
print(np.array(F).shape)
|
||||
ee.make_strain_tensor(np.array(F))
|
||||
ee.make_energy_density(np.array(F))
|
||||
assert np.linalg.norm(ee.psi - np.array(psi_gt)) < eps
|
||||
|
||||
@pytest.mark.timeout(0.5)
|
||||
@pytest.mark.parametrize("data", homework_datas[1])
|
||||
def test_linear_strain(data):
|
||||
young, poisson, F, E_gt = data
|
||||
ee = LinearElasticEnergy(young, poisson)
|
||||
ee.make_strain_tensor(np.array(F))
|
||||
print(np.array(E_gt).shape, np.array(E_gt)[0])
|
||||
assert np.linalg.norm(ee.E - np.array(E_gt)) < eps
|
||||
|
||||
@pytest.mark.timeout(0.5)
|
||||
@pytest.mark.parametrize("data", homework_datas[2])
|
||||
def test_linear_stress(data):
|
||||
young, poisson, F, P_gt = data
|
||||
ee = LinearElasticEnergy(young, poisson)
|
||||
ee.make_strain_tensor(np.array(F))
|
||||
ee.make_piola_kirchhoff_stress_tensor(np.array(F))
|
||||
assert np.linalg.norm(ee.P - np.array(P_gt)) < eps
|
||||
|
||||
|
||||
@pytest.mark.timeout(0.5)
|
||||
@pytest.mark.parametrize("data", homework_datas[3])
|
||||
def test_neo_psi(data):
|
||||
young, poisson, F, psi_gt = data
|
||||
ee = NeoHookeanElasticEnergy(young, poisson)
|
||||
ee.make_energy_density(np.array(F))
|
||||
assert np.linalg.norm(ee.psi - np.array(psi_gt)) < eps
|
||||
|
||||
@pytest.mark.timeout(0.5)
|
||||
@pytest.mark.parametrize("data", homework_datas[4])
|
||||
def test_neo_stress(data):
|
||||
young, poisson, F, P_gt, logJ_gt, Finv_gt = data
|
||||
ee = NeoHookeanElasticEnergy(young, poisson)
|
||||
ee.make_piola_kirchhoff_stress_tensor(np.array(F))
|
||||
assert np.linalg.norm(ee.P - np.array(P_gt)) < eps
|
||||
assert np.linalg.norm(ee.logJ - np.array(logJ_gt)) < eps
|
||||
assert np.linalg.norm(ee.Finv - np.array(Finv_gt)) < eps
|
||||
|
||||
@pytest.mark.timeout(0.5)
|
||||
@pytest.mark.parametrize("data", homework_datas[5])
|
||||
def test_energy_el(data):
|
||||
etype, young, poisson, v, t, rho, pin_idx, force_mass, v_def, ee_gt = data
|
||||
if etype == "linear":
|
||||
ee = LinearElasticEnergy(young, poisson)
|
||||
else:
|
||||
ee = NeoHookeanElasticEnergy(young, poisson)
|
||||
|
||||
es = ElasticSolid(np.array(v), np.array(t), ee, rho=rho, pin_idx=np.array(pin_idx), f_mass=np.array(force_mass))
|
||||
es.update_def_shape(np.array(v_def))
|
||||
assert np.linalg.norm(es.energy_el - np.array(ee_gt)) < eps
|
||||
|
||||
@pytest.mark.timeout(0.5)
|
||||
@pytest.mark.parametrize("data", homework_datas[6])
|
||||
def test_forces_el(data):
|
||||
etype, young, poisson, v, t, rho, pin_idx, force_mass, v_def, ef_gt = data
|
||||
if etype == "linear":
|
||||
ee = LinearElasticEnergy(young, poisson)
|
||||
else:
|
||||
ee = NeoHookeanElasticEnergy(young, poisson)
|
||||
|
||||
es = ElasticSolid(np.array(v), np.array(t), ee, rho=rho, pin_idx=np.array(pin_idx), f_mass=np.array(force_mass))
|
||||
es.update_def_shape(np.array(v_def))
|
||||
assert np.linalg.norm(es.f - np.array(ef_gt)) < eps
|
||||
|
||||
@pytest.mark.timeout(0.5)
|
||||
@pytest.mark.parametrize("data", homework_datas[7])
|
||||
def test_energy_ext(data):
|
||||
etype, young, poisson, v, t, rho, pin_idx, force_mass, v_def, exte_gt = data
|
||||
if etype == "linear":
|
||||
ee = LinearElasticEnergy(young, poisson)
|
||||
else:
|
||||
ee = NeoHookeanElasticEnergy(young, poisson)
|
||||
|
||||
es = ElasticSolid(np.array(v), np.array(t), ee, rho=rho, pin_idx=np.array(pin_idx), f_mass=np.array(force_mass))
|
||||
es.update_def_shape(np.array(v_def))
|
||||
assert np.linalg.norm(es.energy_ext - np.array(exte_gt)) < eps
|
||||
|
||||
@pytest.mark.timeout(0.5)
|
||||
@pytest.mark.parametrize("data", homework_datas[8])
|
||||
def test_forces_ext(data):
|
||||
etype, young, poisson, v, t, rho, pin_idx, force_mass, v_def, fext_gt, fvol_gt = data
|
||||
if etype == "linear":
|
||||
ee = LinearElasticEnergy(young, poisson)
|
||||
else:
|
||||
ee = NeoHookeanElasticEnergy(young, poisson)
|
||||
|
||||
es = ElasticSolid(np.array(v), np.array(t), ee, rho=rho, pin_idx=np.array(pin_idx), f_mass=np.array(force_mass))
|
||||
es.update_def_shape(np.array(v_def))
|
||||
assert np.linalg.norm(es.f_ext - np.array(fext_gt)) < eps
|
||||
assert np.linalg.norm(es.f_vol - np.array(fvol_gt)) < eps
|
||||
@@ -0,0 +1 @@
|
||||
[[[10000000.0, 0.2, [[[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[3.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], [[2.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0Line truncated
|
||||