[{"data":1,"prerenderedAt":2632},["ShallowReactive",2],{"home-posts":3,"palette-posts":2586,"github":2593},[4,781,1221],{"id":5,"title":6,"body":7,"date":768,"description":769,"draft":770,"extension":771,"meta":772,"navigation":181,"path":773,"seo":774,"stem":775,"tags":776,"__hash__":780},"blog\u002Fblog\u002Flive-modal-analysis.md","The shell on the homepage is solved in your browser",{"type":8,"value":9,"toc":763},"minimark",[10,22,27,35,258,463,467,592,752,756,759],[11,12,13,14,21],"p",{},"The structure at the top of the homepage isn't an animation someone keyframed. When the page loads, a Web Worker builds a shell mesh, hands it to ",[15,16,20],"a",{"href":17,"rel":18},"https:\u002F\u002Felementarium.app",[19],"nofollow","tinyfem",", the C++ finite element library behind Elementarium compiled to WebAssembly, and asks it for the first eight natural modes. What you see are the eigenvectors it returns.",[23,24,26],"h2",{"id":25},"building-the-model","Building the model",[11,28,29,30,34],{},"Each model is a parametric surface sampled on a grid. Every grid cell becomes a ",[31,32,33],"code",{},"mitc4shell"," element, and the supports are ordinary Dirichlet boundary conditions:",[36,37,42],"pre",{"className":38,"code":39,"language":40,"meta":41,"style":41},"language-ts shiki shiki-themes github-dark","const domain = new fem.Domain()\ndomain.add_material({ id: 'M', type: 'linear_isotropic_elastic', E: 30e9, nu: 0.2, rho: 2500 })\ndomain.add_section({ id: 'S', type: 'plane', thickness: 0.09 })\ndomain.add_nodes_flat(ids, coords)\ndomain.add_elements(elements)\ndomain.add_bcs(bcs)\n\nconst problem = new fem.ModalAnalysisProblem(domain)\nconst { frequencies } = problem.solve(8)\nconst shape = problem.mode_shape_bulk(0, ids, [fem.DofId.Ux, fem.DofId.Uy, fem.DofId.Uz])\n","ts","",[31,43,44,74,117,143,154,165,176,183,203,235],{"__ignoreMap":41},[45,46,49,53,57,60,63,67,71],"span",{"class":47,"line":48},"line",1,[45,50,52],{"class":51},"snl16","const",[45,54,56],{"class":55},"sDLfK"," domain",[45,58,59],{"class":51}," =",[45,61,62],{"class":51}," new",[45,64,66],{"class":65},"s95oV"," fem.",[45,68,70],{"class":69},"svObZ","Domain",[45,72,73],{"class":65},"()\n",[45,75,77,80,83,86,90,93,96,99,102,105,108,111,114],{"class":47,"line":76},2,[45,78,79],{"class":65},"domain.",[45,81,82],{"class":69},"add_material",[45,84,85],{"class":65},"({ id: ",[45,87,89],{"class":88},"sU2Wk","'M'",[45,91,92],{"class":65},", type: ",[45,94,95],{"class":88},"'linear_isotropic_elastic'",[45,97,98],{"class":65},", E: ",[45,100,101],{"class":55},"30e9",[45,103,104],{"class":65},", nu: ",[45,106,107],{"class":55},"0.2",[45,109,110],{"class":65},", rho: ",[45,112,113],{"class":55},"2500",[45,115,116],{"class":65}," })\n",[45,118,120,122,125,127,130,132,135,138,141],{"class":47,"line":119},3,[45,121,79],{"class":65},[45,123,124],{"class":69},"add_section",[45,126,85],{"class":65},[45,128,129],{"class":88},"'S'",[45,131,92],{"class":65},[45,133,134],{"class":88},"'plane'",[45,136,137],{"class":65},", thickness: ",[45,139,140],{"class":55},"0.09",[45,142,116],{"class":65},[45,144,146,148,151],{"class":47,"line":145},4,[45,147,79],{"class":65},[45,149,150],{"class":69},"add_nodes_flat",[45,152,153],{"class":65},"(ids, coords)\n",[45,155,157,159,162],{"class":47,"line":156},5,[45,158,79],{"class":65},[45,160,161],{"class":69},"add_elements",[45,163,164],{"class":65},"(elements)\n",[45,166,168,170,173],{"class":47,"line":167},6,[45,169,79],{"class":65},[45,171,172],{"class":69},"add_bcs",[45,174,175],{"class":65},"(bcs)\n",[45,177,179],{"class":47,"line":178},7,[45,180,182],{"emptyLinePlaceholder":181},true,"\n",[45,184,186,188,191,193,195,197,200],{"class":47,"line":185},8,[45,187,52],{"class":51},[45,189,190],{"class":55}," problem",[45,192,59],{"class":51},[45,194,62],{"class":51},[45,196,66],{"class":65},[45,198,199],{"class":69},"ModalAnalysisProblem",[45,201,202],{"class":65},"(domain)\n",[45,204,206,208,211,214,217,220,223,226,229,232],{"class":47,"line":205},9,[45,207,52],{"class":51},[45,209,210],{"class":65}," { ",[45,212,213],{"class":55},"frequencies",[45,215,216],{"class":65}," } ",[45,218,219],{"class":51},"=",[45,221,222],{"class":65}," problem.",[45,224,225],{"class":69},"solve",[45,227,228],{"class":65},"(",[45,230,231],{"class":55},"8",[45,233,234],{"class":65},")\n",[45,236,238,240,243,245,247,250,252,255],{"class":47,"line":237},10,[45,239,52],{"class":51},[45,241,242],{"class":55}," shape",[45,244,59],{"class":51},[45,246,222],{"class":65},[45,248,249],{"class":69},"mode_shape_bulk",[45,251,228],{"class":65},[45,253,254],{"class":55},"0",[45,256,257],{"class":65},", ids, [fem.DofId.Ux, fem.DofId.Uy, fem.DofId.Uz])\n",[11,259,260,261,462],{},"The barrel vault is supported on end diaphragms (rigid in their own plane, ",[45,262,265,309],{"className":263},[264],"katex",[45,266,269],{"className":267},[268],"katex-mathml",[270,271,273],"math",{"xmlns":272},"http:\u002F\u002Fwww.w3.org\u002F1998\u002FMath\u002FMathML",[274,275,276,304],"semantics",{},[277,278,279,289,292,299,301],"mrow",{},[280,281,282,286],"msub",{},[283,284,285],"mi",{},"u",[283,287,288],{},"y",[290,291,219],"mo",{},[280,293,294,296],{},[283,295,285],{},[283,297,298],{},"z",[290,300,219],{},[302,303,254],"mn",{},[305,306,308],"annotation",{"encoding":307},"application\u002Fx-tex","u_y = u_z = 0",[45,310,314,394,452],{"className":311,"ariaHidden":313},[312],"katex-html","true",[45,315,318,323,382,387,391],{"className":316},[317],"base",[45,319],{"className":320,"style":322},[321],"strut","height:0.7167em;vertical-align:-0.2861em;",[45,324,327,331],{"className":325},[326],"mord",[45,328,285],{"className":329},[326,330],"mathnormal",[45,332,335],{"className":333},[334],"msupsub",[45,336,340,373],{"className":337},[338,339],"vlist-t","vlist-t2",[45,341,344,368],{"className":342},[343],"vlist-r",[45,345,349],{"className":346,"style":348},[347],"vlist","height:0.1514em;",[45,350,352,357],{"style":351},"top:-2.55em;margin-left:0em;margin-right:0.05em;",[45,353],{"className":354,"style":356},[355],"pstrut","height:2.7em;",[45,358,364],{"className":359},[360,361,362,363],"sizing","reset-size6","size3","mtight",[45,365,288],{"className":366,"style":367},[326,330,363],"margin-right:0.0359em;",[45,369,372],{"className":370},[371],"vlist-s","​",[45,374,376],{"className":375},[343],[45,377,380],{"className":378,"style":379},[347],"height:0.2861em;",[45,381],{},[45,383],{"className":384,"style":386},[385],"mspace","margin-right:0.2778em;",[45,388,219],{"className":389},[390],"mrel",[45,392],{"className":393,"style":386},[385],[45,395,397,401,443,446,449],{"className":396},[317],[45,398],{"className":399,"style":400},[321],"height:0.5806em;vertical-align:-0.15em;",[45,402,404,407],{"className":403},[326],[45,405,285],{"className":406},[326,330],[45,408,410],{"className":409},[334],[45,411,413,434],{"className":412},[338,339],[45,414,416,431],{"className":415},[343],[45,417,419],{"className":418,"style":348},[347],[45,420,421,424],{"style":351},[45,422],{"className":423,"style":356},[355],[45,425,427],{"className":426},[360,361,362,363],[45,428,298],{"className":429,"style":430},[326,330,363],"margin-right:0.044em;",[45,432,372],{"className":433},[371],[45,435,437],{"className":436},[343],[45,438,441],{"className":439,"style":440},[347],"height:0.15em;",[45,442],{},[45,444],{"className":445,"style":386},[385],[45,447,219],{"className":448},[390],[45,450],{"className":451,"style":386},[385],[45,453,455,459],{"className":454},[317],[45,456],{"className":457,"style":458},[321],"height:0.6444em;",[45,460,254],{"className":461},[326],"), the way the Scordelis–Lo roof is. One extra pinned node stops it sliding along its axis.",[23,464,466],{"id":465},"drawing-the-result","Drawing the result",[11,468,469,470,549,550,591],{},"Mode shapes are normalised so the largest nodal translation is 1, then uploaded as vertex attributes. The vertex shader adds ",[45,471,473,510],{"className":472},[264],[45,474,476],{"className":475},[268],[270,477,478],{"xmlns":272},[274,479,480,507],{},[277,481,482,485,489,492,495,498,501,504],{},[283,483,285],{"mathvariant":484},"bold",[486,487,488],"mtext",{}," ",[283,490,491],{},"sin",[290,493,494],{},"⁡",[290,496,228],{"stretchy":497},"false",[283,499,500],{},"ω",[283,502,503],{},"t",[290,505,506],{"stretchy":497},")",[305,508,509],{"encoding":307},"\\mathbf{u}\\,\\sin(\\omega t)",[45,511,513],{"className":512,"ariaHidden":313},[312],[45,514,516,520,524,528,531,535,539,542,545],{"className":515},[317],[45,517],{"className":518,"style":519},[321],"height:1em;vertical-align:-0.25em;",[45,521,285],{"className":522},[326,523],"mathbf",[45,525],{"className":526,"style":527},[385],"margin-right:0.1667em;",[45,529],{"className":530,"style":527},[385],[45,532,491],{"className":533},[534],"mop",[45,536,228],{"className":537},[538],"mopen",[45,540,500],{"className":541,"style":367},[326,330],[45,543,503],{"className":544},[326,330],[45,546,506],{"className":547},[548],"mclose"," to the rest position, and the fragment shader colours ",[45,551,553,573],{"className":552},[264],[45,554,556],{"className":555},[268],[270,557,558],{"xmlns":272},[274,559,560,570],{},[277,561,562,566,568],{},[283,563,565],{"mathvariant":564},"normal","∣",[283,567,285],{"mathvariant":484},[283,569,565],{"mathvariant":564},[305,571,572],{"encoding":307},"|\\mathbf{u}|",[45,574,576],{"className":575,"ariaHidden":313},[312],[45,577,579,582,585,588],{"className":578},[317],[45,580],{"className":581,"style":519},[321],[45,583,565],{"className":584},[326],[45,586,285],{"className":587},[326,523],[45,589,565],{"className":590},[326]," with the same jet colour map Edubeam uses, in discrete bands like a post-processor's contour mode.",[11,593,594,595,751],{},"Real frequencies span an order of magnitude, so the animation speed follows ",[45,596,598,639],{"className":597},[264],[45,599,601],{"className":600},[268],[270,602,603],{"xmlns":272},[274,604,605,636],{},[277,606,607,619,621,624,627,634],{},[280,608,609,616],{},[277,610,611,614],{},[283,612,613],{},"log",[290,615,494],{},[302,617,618],{},"2",[290,620,228],{"stretchy":497},[283,622,623],{},"f",[283,625,626],{"mathvariant":564},"\u002F",[280,628,629,631],{},[283,630,623],{},[302,632,633],{},"1",[290,635,506],{"stretchy":497},[305,637,638],{"encoding":307},"\\log_2(f \u002F f_1)",[45,640,642],{"className":641,"ariaHidden":313},[312],[45,643,645,648,696,699,703,706,748],{"className":644},[317],[45,646],{"className":647,"style":519},[321],[45,649,651,659],{"className":650},[534],[45,652,654,655],{"className":653},[534],"lo",[45,656,658],{"style":657},"margin-right:0.0139em;","g",[45,660,662],{"className":661},[334],[45,663,665,687],{"className":664},[338,339],[45,666,668,684],{"className":667},[343],[45,669,672],{"className":670,"style":671},[347],"height:0.207em;",[45,673,675,678],{"style":674},"top:-2.4559em;margin-right:0.05em;",[45,676],{"className":677,"style":356},[355],[45,679,681],{"className":680},[360,361,362,363],[45,682,618],{"className":683},[326,363],[45,685,372],{"className":686},[371],[45,688,690],{"className":689},[343],[45,691,694],{"className":692,"style":693},[347],"height:0.2441em;",[45,695],{},[45,697,228],{"className":698},[538],[45,700,623],{"className":701,"style":702},[326,330],"margin-right:0.1076em;",[45,704,626],{"className":705},[326],[45,707,709,712],{"className":708},[326],[45,710,623],{"className":711,"style":702},[326,330],[45,713,715],{"className":714},[334],[45,716,718,740],{"className":717},[338,339],[45,719,721,737],{"className":720},[343],[45,722,725],{"className":723,"style":724},[347],"height:0.3011em;",[45,726,728,731],{"style":727},"top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;",[45,729],{"className":730,"style":356},[355],[45,732,734],{"className":733},[360,361,362,363],[45,735,633],{"className":736},[326,363],[45,738,372],{"className":739},[371],[45,741,743],{"className":742},[343],[45,744,746],{"className":745,"style":440},[347],[45,747],{},[45,749,506],{"className":750},[548],". Higher modes still oscillate visibly faster, and none of them turns into a blur.",[23,753,755],{"id":754},"why-bother","Why bother",[11,757,758],{},"Because it's the shortest honest answer to \"what do you do?\" Open the page and the solver runs on your own machine.",[760,761,762],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":41,"searchDepth":76,"depth":76,"links":764},[765,766,767],{"id":25,"depth":76,"text":26},{"id":465,"depth":76,"text":466},{"id":754,"depth":76,"text":755},"2026-10-08","A MITC4 mesh, a real eigenvalue solve and FEA fringes, all client-side.",false,"md",{},"\u002Fblog\u002Flive-modal-analysis",{"title":6,"description":769},"blog\u002Flive-modal-analysis",[777,778,779],"fem","wasm","tresjs","BH-6FDq7nQg-ysFTr9Re3-pjm99De8UzDu2AUHEBApg",{"id":782,"title":783,"body":784,"date":768,"description":1211,"draft":770,"extension":771,"meta":1212,"navigation":181,"path":1213,"seo":1214,"stem":1215,"tags":1216,"__hash__":1220},"blog\u002Fblog\u002Fthreaded-wasm-in-production.md","Multi-threaded WebAssembly in production, and the parts that hang",{"type":8,"value":785,"toc":1205},[786,810,813,817,824,841,865,868,906,910,913,917,932,935,1155,1158,1162,1202],[11,787,788,789,793,794,797,798,801,802,805,806,809],{},"Elementarium's solver is C++ built on Eigen, compiled with Emscripten. It ships as ",[790,791,792],"strong",{},"two"," WebAssembly builds of the same sources: a default single-threaded one, and a ",[31,795,796],{},"-pthread"," one exported as ",[31,799,800],{},"tinyfem\u002Fparallel",". The second exists for one reason: it's the only way Eigen's OpenMP paths get real threads. In the default build ",[31,803,804],{},"omp_get_max_threads()"," is 1, so every ",[31,807,808],{},"#pragma omp parallel for"," runs serially.",[11,811,812],{},"Getting the threaded build to run in a browser takes three things, and each one fails differently.",[23,814,816],{"id":815},"_1-cross-origin-isolation-or-no-sharedarraybuffer","1. Cross-origin isolation, or no SharedArrayBuffer",[11,818,819,820,823],{},"Threads need ",[31,821,822],{},"SharedArrayBuffer",", and browsers only hand that to a page that is cross-origin isolated:",[36,825,829],{"className":826,"code":827,"language":828,"meta":41,"style":41},"language-http shiki shiki-themes github-dark","Cross-Origin-Opener-Policy: same-origin\nCross-Origin-Embedder-Policy: credentialless\n","http",[31,830,831,836],{"__ignoreMap":41},[45,832,833],{"class":47,"line":48},[45,834,835],{},"Cross-Origin-Opener-Policy: same-origin\n",[45,837,838],{"class":47,"line":76},[45,839,840],{},"Cross-Origin-Embedder-Policy: credentialless\n",[11,842,843,846,847,850,851,854,855,858,859,861,862,864],{},[31,844,845],{},"credentialless"," rather than ",[31,848,849],{},"require-corp"," was a deliberate choice. Project thumbnails load as plain ",[31,852,853],{},"\u003Cimg>"," tags from an object store that sends no ",[31,856,857],{},"Cross-Origin-Resource-Policy",". Under ",[31,860,849],{}," they'd go blank. ",[31,863,845],{}," isolates the page just as well, and simply re-fetches such no-cors subresources without credentials.",[11,866,867],{},"Two traps on the Nuxt side:",[869,870,871,891],"ul",{},[872,873,874,877,878,882,883,886,887,890],"li",{},[31,875,876],{},"nuxt-security"," merges route-rule headers ",[879,880,881],"em",{},"underneath"," its own config, so a COOP written in ",[31,884,885],{},"routeRules"," is silently overridden. COOP belongs in ",[31,888,889],{},"security.headers",".",[872,892,893,894,897,898,901,902,905],{},"Its header plugin only hooks the HTML response. COEP and CORP also have to be on the ",[790,895,896],{},"asset"," responses, because each worker script must itself be served with COEP or Chrome refuses to start it on an isolated page. Its defaults also differ by environment (",[31,899,900],{},"unsafe-none"," in dev), which is why ",[31,903,904],{},"crossOriginIsolated"," was never true on the dev server until the values were spelled out.",[23,907,909],{"id":908},"_2-nested-workers","2. Nested workers",[11,911,912],{},"Isolation is necessary but not sufficient. The threaded build spawns its own pool of nested workers, and that is a second thing a given browser can refuse.",[23,914,916],{"id":915},"_3-failures-that-dont-throw","3. Failures that don't throw",[11,918,919,920,923,924,927,928,931],{},"This is the nasty one. When the browser refuses a pthread worker, it fires an ",[31,921,922],{},"error"," event with no message, and Emscripten's init promise then ",[790,925,926],{},"never settles",". A bare ",[31,929,930],{},"await"," leaves the UI on \"warming up\" forever, with a clean console.",[11,933,934],{},"So the init never trusts the threaded build. It races it against a deadline (it normally reports ready in about 250 ms; the deadline is 8 s) and falls back to the serial build on any failure:",[36,936,938],{"className":38,"code":937,"language":40,"meta":41,"style":41},"if (prefer === 'parallel' && globalThis.crossOriginIsolated) {\n  try {\n    const { init } = await import('tinyfem\u002Fparallel')\n    const module = await withDeadline(init(), 8000)\n    return { module, build: 'parallel', ...configureThreads(module, threads) }\n  }\n  catch (err) {\n    console.warn('[tinyfem] Threaded build unavailable, falling back', err)\n  }\n}\nconst { init } = await import('tinyfem')\nconst module = await init()\nreturn { module, build: 'single', ...configureThreads(module, 0) }\n",[31,939,940,960,968,995,1021,1049,1054,1062,1078,1082,1087,1111,1127],{"__ignoreMap":41},[45,941,942,945,948,951,954,957],{"class":47,"line":48},[45,943,944],{"class":51},"if",[45,946,947],{"class":65}," (prefer ",[45,949,950],{"class":51},"===",[45,952,953],{"class":88}," 'parallel'",[45,955,956],{"class":51}," &&",[45,958,959],{"class":65}," globalThis.crossOriginIsolated) {\n",[45,961,962,965],{"class":47,"line":76},[45,963,964],{"class":51},"  try",[45,966,967],{"class":65}," {\n",[45,969,970,973,975,978,980,982,985,988,990,993],{"class":47,"line":119},[45,971,972],{"class":51},"    const",[45,974,210],{"class":65},[45,976,977],{"class":55},"init",[45,979,216],{"class":65},[45,981,219],{"class":51},[45,983,984],{"class":51}," await",[45,986,987],{"class":51}," import",[45,989,228],{"class":65},[45,991,992],{"class":88},"'tinyfem\u002Fparallel'",[45,994,234],{"class":65},[45,996,997,999,1002,1004,1006,1009,1011,1013,1016,1019],{"class":47,"line":145},[45,998,972],{"class":51},[45,1000,1001],{"class":55}," module",[45,1003,59],{"class":51},[45,1005,984],{"class":51},[45,1007,1008],{"class":69}," withDeadline",[45,1010,228],{"class":65},[45,1012,977],{"class":69},[45,1014,1015],{"class":65},"(), ",[45,1017,1018],{"class":55},"8000",[45,1020,234],{"class":65},[45,1022,1023,1026,1029,1032,1035,1038,1041,1043,1046],{"class":47,"line":156},[45,1024,1025],{"class":51},"    return",[45,1027,1028],{"class":65}," { module, build: ",[45,1030,1031],{"class":88},"'parallel'",[45,1033,1034],{"class":65},", ",[45,1036,1037],{"class":51},"...",[45,1039,1040],{"class":69},"configureThreads",[45,1042,228],{"class":65},[45,1044,1045],{"class":55},"module",[45,1047,1048],{"class":65},", threads) }\n",[45,1050,1051],{"class":47,"line":167},[45,1052,1053],{"class":65},"  }\n",[45,1055,1056,1059],{"class":47,"line":178},[45,1057,1058],{"class":51},"  catch",[45,1060,1061],{"class":65}," (err) {\n",[45,1063,1064,1067,1070,1072,1075],{"class":47,"line":185},[45,1065,1066],{"class":65},"    console.",[45,1068,1069],{"class":69},"warn",[45,1071,228],{"class":65},[45,1073,1074],{"class":88},"'[tinyfem] Threaded build unavailable, falling back'",[45,1076,1077],{"class":65},", err)\n",[45,1079,1080],{"class":47,"line":205},[45,1081,1053],{"class":65},[45,1083,1084],{"class":47,"line":237},[45,1085,1086],{"class":65},"}\n",[45,1088,1090,1092,1094,1096,1098,1100,1102,1104,1106,1109],{"class":47,"line":1089},11,[45,1091,52],{"class":51},[45,1093,210],{"class":65},[45,1095,977],{"class":55},[45,1097,216],{"class":65},[45,1099,219],{"class":51},[45,1101,984],{"class":51},[45,1103,987],{"class":51},[45,1105,228],{"class":65},[45,1107,1108],{"class":88},"'tinyfem'",[45,1110,234],{"class":65},[45,1112,1114,1116,1118,1120,1122,1125],{"class":47,"line":1113},12,[45,1115,52],{"class":51},[45,1117,1001],{"class":55},[45,1119,59],{"class":51},[45,1121,984],{"class":51},[45,1123,1124],{"class":69}," init",[45,1126,73],{"class":65},[45,1128,1130,1133,1135,1138,1140,1142,1144,1146,1148,1150,1152],{"class":47,"line":1129},13,[45,1131,1132],{"class":51},"return",[45,1134,1028],{"class":65},[45,1136,1137],{"class":88},"'single'",[45,1139,1034],{"class":65},[45,1141,1037],{"class":51},[45,1143,1040],{"class":69},[45,1145,228],{"class":65},[45,1147,1045],{"class":55},[45,1149,1034],{"class":65},[45,1151,254],{"class":55},[45,1153,1154],{"class":65},") }\n",[11,1156,1157],{},"A slow solve beats a dead one. The warning is loud on purpose: nothing else in the UI distinguishes a threaded solve from a serial one, so without it the degradation is invisible.",[23,1159,1161],{"id":1160},"smaller-things-that-bit","Smaller things that bit",[869,1163,1164,1182,1188],{},[872,1165,1166,1169,1170,1173,1174,1177,1178,1181],{},[790,1167,1168],{},"Read the ceiling before you cap."," ",[31,1171,1172],{},"get_omp_max_threads()"," returns the ",[879,1175,1176],{},"current"," setting, not the hardware limit. Read it first, then call ",[31,1179,1180],{},"set_omp_num_threads",", or the real number is gone.",[872,1183,1184,1187],{},[790,1185,1186],{},"One decision for every worker."," The solver worker and the mesh worker both go through the same init. The builds are separate ~4 MB binaries; picking different ones per worker would put both on the wire instead of letting the second hit the HTTP cache.",[872,1189,1190,1193,1194,1197,1198,1201],{},[790,1191,1192],{},"Static hosting needs its own headers."," None of this reaches the browser from ",[31,1195,1196],{},"nuxt generate"," output unless the host sets COEP and CORP for ",[31,1199,1200],{},"\u002F_nuxt\u002F**"," as well.",[760,1203,1204],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":41,"searchDepth":76,"depth":76,"links":1206},[1207,1208,1209,1210],{"id":815,"depth":76,"text":816},{"id":908,"depth":76,"text":909},{"id":915,"depth":76,"text":916},{"id":1160,"depth":76,"text":1161},"Shipping a C++ FEM solver with OpenMP threads to the browser. Isolation headers, nested workers, and why the fallback needs a deadline.",{},"\u002Fblog\u002Fthreaded-wasm-in-production",{"title":783,"description":1211},"blog\u002Fthreaded-wasm-in-production",[778,1217,1218,1219],"emscripten","openmp","nuxt","Ma_juvvY-Ss7yWlmpSzrVuORPTMZpAx9tH7V9F81rnU",{"id":1222,"title":1223,"body":1224,"date":2576,"description":2577,"draft":770,"extension":771,"meta":2578,"navigation":181,"path":2579,"seo":2580,"stem":2581,"tags":2582,"__hash__":2585},"blog\u002Fblog\u002Fhow-many-modes.md","How many modes is enough?",{"type":8,"value":1225,"toc":2570},[1226,1229,1233,1240,1251,1317,2076,2235,2239,2378,2549,2552,2556,2559,2563],[11,1227,1228],{},"Every modal analysis dialog asks the same question up front: how many modes? Nobody can answer that honestly in advance. It depends on the structure. Here's how Elementarium approaches it instead.",[23,1230,1232],{"id":1231},"ask-for-mass-not-a-mode-count","Ask for mass, not a mode count",[11,1234,1235,1236,1239],{},"The seismic codes don't care about a number of modes. They care about how much of the structure's mass takes part. EN 1998-1 §4.3.3.3 asks for the modes considered to activate at least ",[790,1237,1238],{},"90 %"," of the total mass in each direction.",[11,1241,1242,1243,1246,1247,1250],{},"So a modal setup carries a ",[879,1244,1245],{},"mass target"," alongside the requested mode count. The solver keeps extracting until the participating mass reaches the target, with a hard ceiling (",[31,1248,1249],{},"maxModes",") behind it. The \"lowest N modes\" request becomes a floor rather than a guess.",[11,1252,1253,1254,1284,1285,1316],{},"Mass participation for mode ",[45,1255,1257,1271],{"className":1256},[264],[45,1258,1260],{"className":1259},[268],[270,1261,1262],{"xmlns":272},[274,1263,1264,1269],{},[277,1265,1266],{},[283,1267,1268],{},"i",[305,1270,1268],{"encoding":307},[45,1272,1274],{"className":1273,"ariaHidden":313},[312],[45,1275,1277,1281],{"className":1276},[317],[45,1278],{"className":1279,"style":1280},[321],"height:0.6595em;",[45,1282,1268],{"className":1283},[326,330]," in direction ",[45,1286,1288,1302],{"className":1287},[264],[45,1289,1291],{"className":1290},[268],[270,1292,1293],{"xmlns":272},[274,1294,1295,1300],{},[277,1296,1297],{},[283,1298,1299],{},"r",[305,1301,1299],{"encoding":307},[45,1303,1305],{"className":1304,"ariaHidden":313},[312],[45,1306,1308,1312],{"className":1307},[317],[45,1309],{"className":1310,"style":1311},[321],"height:0.4306em;",[45,1313,1299],{"className":1314,"style":1315},[326,330],"margin-right:0.0278em;"," is",[45,1318,1321],{"className":1319},[1320],"katex-display",[45,1322,1324,1466],{"className":1323},[264],[45,1325,1327],{"className":1326},[268],[270,1328,1330],{"xmlns":272,"display":1329},"block",[274,1331,1332,1463],{},[277,1333,1334,1348,1350,1399,1401,1404,1422,1424,1438,1441,1449,1451,1453,1455,1461],{},[280,1335,1336,1339],{},[283,1337,1338],{"mathvariant":564},"Γ",[277,1340,1341,1343,1346],{},[283,1342,1268],{},[290,1344,1345],{"separator":313},",",[283,1347,1299],{},[290,1349,219],{},[1351,1352,1353,1377],"mfrac",{},[277,1354,1355,1368,1370,1373,1375],{},[1356,1357,1358,1362,1364],"msubsup",{},[283,1359,1361],{"mathvariant":1360},"bold-italic","ϕ",[283,1363,1268],{},[283,1365,1367],{"mathvariant":1366},"sans-serif","T",[486,1369,488],{},[283,1371,1372],{"mathvariant":484},"M",[486,1374,488],{},[283,1376,1299],{"mathvariant":484},[277,1378,1379,1387,1389,1391,1393],{},[1356,1380,1381,1383,1385],{},[283,1382,1361],{"mathvariant":1360},[283,1384,1268],{},[283,1386,1367],{"mathvariant":1366},[486,1388,488],{},[283,1390,1372],{"mathvariant":484},[486,1392,488],{},[280,1394,1395,1397],{},[283,1396,1361],{"mathvariant":1360},[283,1398,1268],{},[290,1400,1345],{"separator":313},[385,1402],{"width":1403},"2em",[280,1405,1406,1409],{},[283,1407,1408],{},"m",[277,1410,1411,1414,1416,1418,1420],{},[486,1412,1413],{},"eff",[290,1415,1345],{"separator":313},[283,1417,1268],{},[290,1419,1345],{"separator":313},[283,1421,1299],{},[290,1423,219],{},[1356,1425,1426,1428,1436],{},[283,1427,1338],{"mathvariant":564},[277,1429,1430,1432,1434],{},[283,1431,1268],{},[290,1433,1345],{"separator":313},[283,1435,1299],{},[302,1437,618],{},[486,1439,1440],{},"  ",[1356,1442,1443,1445,1447],{},[283,1444,1361],{"mathvariant":1360},[283,1446,1268],{},[283,1448,1367],{"mathvariant":1366},[486,1450,488],{},[283,1452,1372],{"mathvariant":484},[486,1454,488],{},[280,1456,1457,1459],{},[283,1458,1361],{"mathvariant":1360},[283,1460,1268],{},[290,1462,1345],{"separator":313},[305,1464,1465],{"encoding":307},"\\Gamma_{i,r} = \\frac{\\boldsymbol{\\phi}_i^{\\mathsf T}\\,\\mathbf{M}\\,\\mathbf{r}}{\\boldsymbol{\\phi}_i^{\\mathsf T}\\,\\mathbf{M}\\,\\boldsymbol{\\phi}_i},\n\\qquad\nm_{\\text{eff},i,r} = \\Gamma_{i,r}^{2}\\;\\boldsymbol{\\phi}_i^{\\mathsf T}\\,\\mathbf{M}\\,\\boldsymbol{\\phi}_i,",[45,1467,1469,1536,1881],{"className":1468,"ariaHidden":313},[312],[45,1470,1472,1476,1527,1530,1533],{"className":1471},[317],[45,1473],{"className":1474,"style":1475},[321],"height:0.9694em;vertical-align:-0.2861em;",[45,1477,1479,1482],{"className":1478},[326],[45,1480,1338],{"className":1481},[326],[45,1483,1485],{"className":1484},[334],[45,1486,1488,1519],{"className":1487},[338,339],[45,1489,1491,1516],{"className":1490},[343],[45,1492,1495],{"className":1493,"style":1494},[347],"height:0.3117em;",[45,1496,1497,1500],{"style":351},[45,1498],{"className":1499,"style":356},[355],[45,1501,1503],{"className":1502},[360,361,362,363],[45,1504,1506,1509,1513],{"className":1505},[326,363],[45,1507,1268],{"className":1508},[326,330,363],[45,1510,1345],{"className":1511},[1512,363],"mpunct",[45,1514,1299],{"className":1515,"style":1315},[326,330,363],[45,1517,372],{"className":1518},[371],[45,1520,1522],{"className":1521},[343],[45,1523,1525],{"className":1524,"style":379},[347],[45,1526],{},[45,1528],{"className":1529,"style":386},[385],[45,1531,219],{"className":1532},[390],[45,1534],{"className":1535,"style":386},[385],[45,1537,1539,1543,1802,1805,1809,1812,1872,1875,1878],{"className":1538},[317],[45,1540],{"className":1541,"style":1542},[321],"height:2.6809em;vertical-align:-1.0704em;",[45,1544,1546,1550,1799],{"className":1545},[326],[45,1547],{"className":1548},[538,1549],"nulldelimiter",[45,1551,1553],{"className":1552},[1351],[45,1554,1556,1790],{"className":1555},[338,339],[45,1557,1559,1787],{"className":1558},[343],[45,1560,1563,1695,1706],{"className":1561,"style":1562},[347],"height:1.6104em;",[45,1564,1566,1570],{"style":1565},"top:-2.1766em;",[45,1567],{"className":1568,"style":1569},[355],"height:3em;",[45,1571,1573,1639,1642,1645,1648],{"className":1572},[326],[45,1574,1576,1586],{"className":1575},[326],[45,1577,1579],{"className":1578},[326],[45,1580,1582],{"className":1581},[326],[45,1583,1361],{"className":1584},[326,1585],"boldsymbol",[45,1587,1589],{"className":1588},[334],[45,1590,1592,1630],{"className":1591},[338,339],[45,1593,1595,1627],{"className":1594},[343],[45,1596,1599,1611],{"className":1597,"style":1598},[347],"height:0.9334em;",[45,1600,1602,1605],{"style":1601},"top:-2.453em;margin-right:0.05em;",[45,1603],{"className":1604,"style":356},[355],[45,1606,1608],{"className":1607},[360,361,362,363],[45,1609,1268],{"className":1610},[326,330,363],[45,1612,1614,1617],{"style":1613},"top:-3.1473em;margin-right:0.05em;",[45,1615],{"className":1616,"style":356},[355],[45,1618,1620],{"className":1619},[360,361,362,363],[45,1621,1623],{"className":1622},[326,363],[45,1624,1367],{"className":1625},[326,1626,363],"mathsf",[45,1628,372],{"className":1629},[371],[45,1631,1633],{"className":1632},[343],[45,1634,1637],{"className":1635,"style":1636},[347],"height:0.247em;",[45,1638],{},[45,1640],{"className":1641,"style":527},[385],[45,1643,1372],{"className":1644},[326,523],[45,1646],{"className":1647,"style":527},[385],[45,1649,1651,1660],{"className":1650},[326],[45,1652,1654],{"className":1653},[326],[45,1655,1657],{"className":1656},[326],[45,1658,1361],{"className":1659},[326,1585],[45,1661,1663],{"className":1662},[334],[45,1664,1666,1687],{"className":1665},[338,339],[45,1667,1669,1684],{"className":1668},[343],[45,1670,1673],{"className":1671,"style":1672},[347],"height:0.2175em;",[45,1674,1675,1678],{"style":674},[45,1676],{"className":1677,"style":356},[355],[45,1679,1681],{"className":1680},[360,361,362,363],[45,1682,1268],{"className":1683},[326,330,363],[45,1685,372],{"className":1686},[371],[45,1688,1690],{"className":1689},[343],[45,1691,1693],{"className":1692,"style":693},[347],[45,1694],{},[45,1696,1698,1701],{"style":1697},"top:-3.23em;",[45,1699],{"className":1700,"style":1569},[355],[45,1702],{"className":1703,"style":1705},[1704],"frac-line","border-bottom-width:0.04em;",[45,1707,1709,1712],{"style":1708},"top:-3.677em;",[45,1710],{"className":1711,"style":1569},[355],[45,1713,1715,1775,1778,1781,1784],{"className":1714},[326],[45,1716,1718,1727],{"className":1717},[326],[45,1719,1721],{"className":1720},[326],[45,1722,1724],{"className":1723},[326],[45,1725,1361],{"className":1726},[326,1585],[45,1728,1730],{"className":1729},[334],[45,1731,1733,1767],{"className":1732},[338,339],[45,1734,1736,1764],{"className":1735},[343],[45,1737,1739,1750],{"className":1738,"style":1598},[347],[45,1740,1741,1744],{"style":1601},[45,1742],{"className":1743,"style":356},[355],[45,1745,1747],{"className":1746},[360,361,362,363],[45,1748,1268],{"className":1749},[326,330,363],[45,1751,1752,1755],{"style":1613},[45,1753],{"className":1754,"style":356},[355],[45,1756,1758],{"className":1757},[360,361,362,363],[45,1759,1761],{"className":1760},[326,363],[45,1762,1367],{"className":1763},[326,1626,363],[45,1765,372],{"className":1766},[371],[45,1768,1770],{"className":1769},[343],[45,1771,1773],{"className":1772,"style":1636},[347],[45,1774],{},[45,1776],{"className":1777,"style":527},[385],[45,1779,1372],{"className":1780},[326,523],[45,1782],{"className":1783,"style":527},[385],[45,1785,1299],{"className":1786},[326,523],[45,1788,372],{"className":1789},[371],[45,1791,1793],{"className":1792},[343],[45,1794,1797],{"className":1795,"style":1796},[347],"height:1.0704em;",[45,1798],{},[45,1800],{"className":1801},[548,1549],[45,1803,1345],{"className":1804},[1512],[45,1806],{"className":1807,"style":1808},[385],"margin-right:2em;",[45,1810],{"className":1811,"style":527},[385],[45,1813,1815,1818],{"className":1814},[326],[45,1816,1408],{"className":1817},[326,330],[45,1819,1821],{"className":1820},[334],[45,1822,1824,1864],{"className":1823},[338,339],[45,1825,1827,1861],{"className":1826},[343],[45,1828,1831],{"className":1829,"style":1830},[347],"height:0.3361em;",[45,1832,1833,1836],{"style":351},[45,1834],{"className":1835,"style":356},[355],[45,1837,1839],{"className":1838},[360,361,362,363],[45,1840,1842,1849,1852,1855,1858],{"className":1841},[326,363],[45,1843,1846],{"className":1844},[326,1845,363],"text",[45,1847,1413],{"className":1848},[326,363],[45,1850,1345],{"className":1851},[1512,363],[45,1853,1268],{"className":1854},[326,330,363],[45,1856,1345],{"className":1857},[1512,363],[45,1859,1299],{"className":1860,"style":1315},[326,330,363],[45,1862,372],{"className":1863},[371],[45,1865,1867],{"className":1866},[343],[45,1868,1870],{"className":1869,"style":379},[347],[45,1871],{},[45,1873],{"className":1874,"style":386},[385],[45,1876,219],{"className":1877},[390],[45,1879],{"className":1880,"style":386},[385],[45,1882,1884,1888,1955,1958,2018,2021,2024,2027,2073],{"className":1883},[317],[45,1885],{"className":1886,"style":1887},[321],"height:1.3166em;vertical-align:-0.3831em;",[45,1889,1891,1894],{"className":1890},[326],[45,1892,1338],{"className":1893},[326],[45,1895,1897],{"className":1896},[334],[45,1898,1900,1946],{"className":1899},[338,339],[45,1901,1903,1943],{"className":1902},[343],[45,1904,1907,1928],{"className":1905,"style":1906},[347],"height:0.8641em;",[45,1908,1910,1913],{"style":1909},"top:-2.453em;margin-left:0em;margin-right:0.05em;",[45,1911],{"className":1912,"style":356},[355],[45,1914,1916],{"className":1915},[360,361,362,363],[45,1917,1919,1922,1925],{"className":1918},[326,363],[45,1920,1268],{"className":1921},[326,330,363],[45,1923,1345],{"className":1924},[1512,363],[45,1926,1299],{"className":1927,"style":1315},[326,330,363],[45,1929,1931,1934],{"style":1930},"top:-3.113em;margin-right:0.05em;",[45,1932],{"className":1933,"style":356},[355],[45,1935,1937],{"className":1936},[360,361,362,363],[45,1938,1940],{"className":1939},[326,363],[45,1941,618],{"className":1942},[326,363],[45,1944,372],{"className":1945},[371],[45,1947,1949],{"className":1948},[343],[45,1950,1953],{"className":1951,"style":1952},[347],"height:0.3831em;",[45,1954],{},[45,1956],{"className":1957,"style":386},[385],[45,1959,1961,1970],{"className":1960},[326],[45,1962,1964],{"className":1963},[326],[45,1965,1967],{"className":1966},[326],[45,1968,1361],{"className":1969},[326,1585],[45,1971,1973],{"className":1972},[334],[45,1974,1976,2010],{"className":1975},[338,339],[45,1977,1979,2007],{"className":1978},[343],[45,1980,1982,1993],{"className":1981,"style":1598},[347],[45,1983,1984,1987],{"style":1601},[45,1985],{"className":1986,"style":356},[355],[45,1988,1990],{"className":1989},[360,361,362,363],[45,1991,1268],{"className":1992},[326,330,363],[45,1994,1995,1998],{"style":1613},[45,1996],{"className":1997,"style":356},[355],[45,1999,2001],{"className":2000},[360,361,362,363],[45,2002,2004],{"className":2003},[326,363],[45,2005,1367],{"className":2006},[326,1626,363],[45,2008,372],{"className":2009},[371],[45,2011,2013],{"className":2012},[343],[45,2014,2016],{"className":2015,"style":1636},[347],[45,2017],{},[45,2019],{"className":2020,"style":527},[385],[45,2022,1372],{"className":2023},[326,523],[45,2025],{"className":2026,"style":527},[385],[45,2028,2030,2039],{"className":2029},[326],[45,2031,2033],{"className":2032},[326],[45,2034,2036],{"className":2035},[326],[45,2037,1361],{"className":2038},[326,1585],[45,2040,2042],{"className":2041},[334],[45,2043,2045,2065],{"className":2044},[338,339],[45,2046,2048,2062],{"className":2047},[343],[45,2049,2051],{"className":2050,"style":1672},[347],[45,2052,2053,2056],{"style":674},[45,2054],{"className":2055,"style":356},[355],[45,2057,2059],{"className":2058},[360,361,362,363],[45,2060,1268],{"className":2061},[326,330,363],[45,2063,372],{"className":2064},[371],[45,2066,2068],{"className":2067},[343],[45,2069,2071],{"className":2070,"style":693},[347],[45,2072],{},[45,2074,1345],{"className":2075},[1512],[11,2077,2078,2079,2234],{},"and the target is met when ",[45,2080,2082,2117],{"className":2081},[264],[45,2083,2085],{"className":2084},[268],[270,2086,2087],{"xmlns":272},[274,2088,2089,2114],{},[277,2090,2091,2098],{},[280,2092,2093,2096],{},[290,2094,2095],{},"∑",[283,2097,1268],{},[280,2099,2100,2102],{},[283,2101,1408],{},[277,2103,2104,2106,2108,2110,2112],{},[486,2105,1413],{},[290,2107,1345],{"separator":313},[283,2109,1268],{},[290,2111,1345],{"separator":313},[283,2113,1299],{},[305,2115,2116],{"encoding":307},"\\sum_i m_{\\text{eff},i,r}",[45,2118,2120],{"className":2119,"ariaHidden":313},[312],[45,2121,2123,2127,2173,2176],{"className":2122},[317],[45,2124],{"className":2125,"style":2126},[321],"height:1.0497em;vertical-align:-0.2997em;",[45,2128,2130,2136],{"className":2129},[534],[45,2131,2095],{"className":2132,"style":2135},[534,2133,2134],"op-symbol","small-op","position:relative;top:0em;",[45,2137,2139],{"className":2138},[334],[45,2140,2142,2164],{"className":2141},[338,339],[45,2143,2145,2161],{"className":2144},[343],[45,2146,2149],{"className":2147,"style":2148},[347],"height:0.162em;",[45,2150,2152,2155],{"style":2151},"top:-2.4003em;margin-left:0em;margin-right:0.05em;",[45,2153],{"className":2154,"style":356},[355],[45,2156,2158],{"className":2157},[360,361,362,363],[45,2159,1268],{"className":2160},[326,330,363],[45,2162,372],{"className":2163},[371],[45,2165,2167],{"className":2166},[343],[45,2168,2171],{"className":2169,"style":2170},[347],"height:0.2997em;",[45,2172],{},[45,2174],{"className":2175,"style":527},[385],[45,2177,2179,2182],{"className":2178},[326],[45,2180,1408],{"className":2181},[326,330],[45,2183,2185],{"className":2184},[334],[45,2186,2188,2226],{"className":2187},[338,339],[45,2189,2191,2223],{"className":2190},[343],[45,2192,2194],{"className":2193,"style":1830},[347],[45,2195,2196,2199],{"style":351},[45,2197],{"className":2198,"style":356},[355],[45,2200,2202],{"className":2201},[360,361,362,363],[45,2203,2205,2211,2214,2217,2220],{"className":2204},[326,363],[45,2206,2208],{"className":2207},[326,1845,363],[45,2209,1413],{"className":2210},[326,363],[45,2212,1345],{"className":2213},[1512,363],[45,2215,1268],{"className":2216},[326,330,363],[45,2218,1345],{"className":2219},[1512,363],[45,2221,1299],{"className":2222,"style":1315},[326,330,363],[45,2224,372],{"className":2225},[371],[45,2227,2229],{"className":2228},[343],[45,2230,2232],{"className":2231,"style":379},[347],[45,2233],{}," reaches 90 % of the total mass.",[23,2236,2238],{"id":2237},"the-mode-you-didnt-get","The mode you didn't get",[11,2240,2241,2242,2245,2246,2373,2374,2377],{},"Iterative eigensolvers (Krylov, subspace iteration) are fast on large models. They have one quiet failure: they can ",[790,2243,2244],{},"step over"," a mode. Every returned pair still passes its residual test, ",[45,2247,2249,2285],{"className":2248},[264],[45,2250,2252],{"className":2251},[268],[270,2253,2254],{"xmlns":272},[274,2255,2256,2282],{},[277,2257,2258,2261,2264,2266,2269,2276,2278,2280],{},[290,2259,2260],{"stretchy":497},"∥",[283,2262,2263],{"mathvariant":484},"K",[283,2265,1361],{"mathvariant":1360},[290,2267,2268],{},"−",[2270,2271,2272,2274],"msup",{},[283,2273,500],{},[302,2275,618],{},[283,2277,1372],{"mathvariant":484},[283,2279,1361],{"mathvariant":1360},[290,2281,2260],{"stretchy":497},[305,2283,2284],{"encoding":307},"\\lVert \\mathbf{K}\\boldsymbol\\phi - \\omega^2\\mathbf{M}\\boldsymbol\\phi \\rVert",[45,2286,2288,2320],{"className":2287,"ariaHidden":313},[312],[45,2289,2291,2294,2297,2300,2309,2313,2317],{"className":2290},[317],[45,2292],{"className":2293,"style":519},[321],[45,2295,2260],{"className":2296},[538],[45,2298,2263],{"className":2299},[326,523],[45,2301,2303],{"className":2302},[326],[45,2304,2306],{"className":2305},[326],[45,2307,1361],{"className":2308},[326,1585],[45,2310],{"className":2311,"style":2312},[385],"margin-right:0.2222em;",[45,2314,2268],{"className":2315},[2316],"mbin",[45,2318],{"className":2319,"style":2312},[385],[45,2321,2323,2327,2358,2361,2370],{"className":2322},[317],[45,2324],{"className":2325,"style":2326},[321],"height:1.0641em;vertical-align:-0.25em;",[45,2328,2330,2333],{"className":2329},[326],[45,2331,500],{"className":2332,"style":367},[326,330],[45,2334,2336],{"className":2335},[334],[45,2337,2339],{"className":2338},[338],[45,2340,2342],{"className":2341},[343],[45,2343,2346],{"className":2344,"style":2345},[347],"height:0.8141em;",[45,2347,2349,2352],{"style":2348},"top:-3.063em;margin-right:0.05em;",[45,2350],{"className":2351,"style":356},[355],[45,2353,2355],{"className":2354},[360,361,362,363],[45,2356,618],{"className":2357},[326,363],[45,2359,1372],{"className":2360},[326,523],[45,2362,2364],{"className":2363},[326],[45,2365,2367],{"className":2366},[326],[45,2368,1361],{"className":2369},[326,1585],[45,2371,2260],{"className":2372},[548]," is small, but the set isn't the ",[879,2375,2376],{},"lowest"," set. The results come out 1–4 % wrong, and nobody would catch that by eye.",[11,2379,2380,2381,2384,2385,2444,2445,2518,2519,2548],{},"The fix is old and cheap: a ",[790,2382,2383],{},"Sturm-sequence check",". Factor the shifted matrix ",[45,2386,2388,2409],{"className":2387},[264],[45,2389,2391],{"className":2390},[268],[270,2392,2393],{"xmlns":272},[274,2394,2395,2406],{},[277,2396,2397,2399,2401,2404],{},[283,2398,2263],{"mathvariant":484},[290,2400,2268],{},[283,2402,2403],{},"σ",[283,2405,1372],{"mathvariant":484},[305,2407,2408],{"encoding":307},"\\mathbf{K} - \\sigma\\mathbf{M}",[45,2410,2412,2431],{"className":2411,"ariaHidden":313},[312],[45,2413,2415,2419,2422,2425,2428],{"className":2414},[317],[45,2416],{"className":2417,"style":2418},[321],"height:0.7694em;vertical-align:-0.0833em;",[45,2420,2263],{"className":2421},[326,523],[45,2423],{"className":2424,"style":2312},[385],[45,2426,2268],{"className":2427},[2316],[45,2429],{"className":2430,"style":2312},[385],[45,2432,2434,2438,2441],{"className":2433},[317],[45,2435],{"className":2436,"style":2437},[321],"height:0.6861em;",[45,2439,2403],{"className":2440,"style":367},[326,330],[45,2442,1372],{"className":2443},[326,523]," just above the highest returned eigenvalue, and count the negative pivots in ",[45,2446,2448,2472],{"className":2447},[264],[45,2449,2451],{"className":2450},[268],[270,2452,2453],{"xmlns":272},[274,2454,2455,2469],{},[277,2456,2457,2460,2463],{},[283,2458,2459],{"mathvariant":484},"L",[283,2461,2462],{"mathvariant":484},"D",[2270,2464,2465,2467],{},[283,2466,2459],{"mathvariant":484},[283,2468,1367],{"mathvariant":1366},[305,2470,2471],{"encoding":307},"\\mathbf{L}\\mathbf{D}\\mathbf{L}^{\\mathsf T}",[45,2473,2475],{"className":2474,"ariaHidden":313},[312],[45,2476,2478,2482,2486],{"className":2477},[317],[45,2479],{"className":2480,"style":2481},[321],"height:0.8491em;",[45,2483,2485],{"className":2484},[326,523],"LD",[45,2487,2489,2492],{"className":2488},[326],[45,2490,2459],{"className":2491},[326,523],[45,2493,2495],{"className":2494},[334],[45,2496,2498],{"className":2497},[338],[45,2499,2501],{"className":2500},[343],[45,2502,2504],{"className":2503,"style":2481},[347],[45,2505,2506,2509],{"style":2348},[45,2507],{"className":2508,"style":356},[355],[45,2510,2512],{"className":2511},[360,361,362,363],[45,2513,2515],{"className":2514},[326,363],[45,2516,1367],{"className":2517},[326,1626,363],". That count equals the number of eigenvalues below ",[45,2520,2522,2536],{"className":2521},[264],[45,2523,2525],{"className":2524},[268],[270,2526,2527],{"xmlns":272},[274,2528,2529,2533],{},[277,2530,2531],{},[283,2532,2403],{},[305,2534,2535],{"encoding":307},"\\sigma",[45,2537,2539],{"className":2538,"ariaHidden":313},[312],[45,2540,2542,2545],{"className":2541},[317],[45,2543],{"className":2544,"style":1311},[321],[45,2546,2403],{"className":2547,"style":367},[326,330],". If it's larger than the number of modes you got, one was skipped.",[11,2550,2551],{},"It costs one extra sparse factorization, so in Elementarium it's on by default.",[23,2553,2555],{"id":2554},"consistent-or-lumped","Consistent or lumped",[11,2557,2558],{},"A consistent mass matrix bounds the frequencies from above. A lumped one typically lands below. Together they bracket the exact answer for a given mesh. Consistent is the default because it's the more accurate of the two for the same number of DOFs.",[23,2560,2562],{"id":2561},"the-mesh-is-part-of-the-question","The mesh is part of the question",[11,2564,2565,2566,2569],{},"The last setting that matters isn't a solver option at all: how finely members are divided for the analysis. A member meshed as a single element has no mode shape of its own. So the modal setup sets a ",[879,2567,2568],{},"floor"," on member divisions, and it overrides a coarser count set on an individual member. Two setups can legitimately disagree: a coarse one for a quick storey-mass check, and a fine one that resolves the local modes of individual members.",{"title":41,"searchDepth":76,"depth":76,"links":2571},[2572,2573,2574,2575],{"id":1231,"depth":76,"text":1232},{"id":2237,"depth":76,"text":2238},{"id":2554,"depth":76,"text":2555},{"id":2561,"depth":76,"text":2562},"2026-10-07","Mass participation targets, eigensolvers that quietly skip a mode, and the Sturm-sequence check that catches it.",{},"\u002Fblog\u002Fhow-many-modes",{"title":1223,"description":2577},"blog\u002Fhow-many-modes",[777,2583,2584],"dynamics","eurocode","mzc3HEKB85FQDCFnay5eihAR8dUIAEs_0iZQL0-GA0Q",[2587,2590,2591,2592],{"title":2588,"path":2589},"Hello","\u002Fblog\u002Fhello",{"title":1223,"path":2579},{"title":6,"path":773},{"title":783,"path":1213},{"chinese-latex-utilities":2594,"drie":2599,"edubeam":2604,"finetoolsheatdiffx":2609,"gcodeparser.jl":2614,"janvorisek":2617,"minimal-latex-cv":2619,"solidmodeling.jl":2624,"ts-fem":2627,"v-dock":2630},{"stars":2595,"forks":237,"language":2596,"pushed":2597,"description":2598},27,"TeX","2018-08-22T15:27:00Z","Utilities for chinese in LaTeX. Create practise sheets, dialogs, character explanations and more. There are PDFs included which may be useful to regular users.",{"stars":2600,"forks":76,"language":2601,"pushed":2602,"description":2603},75,"Vue","2023-07-07T14:38:01Z","Drie is a Vue 3 component library for THREE.js made with TypeScript and Composition API.",{"stars":2605,"forks":2606,"language":2601,"pushed":2607,"description":2608},53,17,"2026-10-08T05:33:01Z","Free online structural analysis tool for beams and trusses. Edubeam lets you create and solve 2D structures directly in your browser — no installation required. Instantly generate bending moment diagrams, shear force diagrams, and deflection plots. Ideal for students, educators, and engineers.",{"stars":2610,"forks":2610,"language":2611,"pushed":2612,"description":2613},0,"Julia","2020-02-17T13:01:37Z",null,{"stars":48,"forks":2610,"language":2611,"pushed":2615,"description":2616},"2020-02-14T09:36:52Z","Simple package for g-code parsing in Julia",{"stars":2610,"forks":2610,"language":2613,"pushed":2618,"description":2613},"2025-12-06T16:34:34Z",{"stars":2620,"forks":2621,"language":2596,"pushed":2622,"description":2623},38,14,"2018-08-16T15:34:16Z","Minimal resumé template written in LaTeX. Just black and white making it printable without problems.",{"stars":156,"forks":48,"language":2611,"pushed":2625,"description":2626},"2020-05-07T15:42:09Z","Perform boolean operations on solids in Julia - union, intersection and subtraction",{"stars":76,"forks":145,"language":2628,"pushed":2629,"description":2613},"TypeScript","2026-05-20T12:17:41Z",{"stars":2610,"forks":2610,"language":2601,"pushed":2631,"description":2613},"2024-03-25T18:24:17Z",1791460413146]