From 3b4b8be8ec0c356aab101c5bb789846d44c2aa4b Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Wed, 6 Aug 2025 16:07:14 -0500 Subject: [PATCH 01/52] example --- doc/source/conf.py | 1 + examples/setup/01_setup.py | 65 ++++++++++++++++++++++++++++++++ examples/setup/out/test.mechdat | Bin 0 -> 4766920 bytes examples/setup/readme.txt | 4 ++ 4 files changed, 70 insertions(+) create mode 100644 examples/setup/01_setup.py create mode 100644 examples/setup/out/test.mechdat create mode 100644 examples/setup/readme.txt diff --git a/doc/source/conf.py b/doc/source/conf.py index 5ab185673..28a53c4dd 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -239,6 +239,7 @@ "sidebar_pages": ["changelog", "index"], }, "ansys_sphinx_theme_autoapi": {"project": project, "templates": "_templates/autoapi"}, + "show_nav_level": 0, } if BUILD_CHEATSHEET: diff --git a/examples/setup/01_setup.py b/examples/setup/01_setup.py new file mode 100644 index 000000000..409cf767d --- /dev/null +++ b/examples/setup/01_setup.py @@ -0,0 +1,65 @@ +""".. _ref_setup: + +App +--- + +This section has helper scripts for Embedded App +""" +# %% +# Create an embedded instance and open an existing Mechanical File +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file + +mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") +app = App(db_file = mechdat_path, globals=globals()) +print(app) + + +# %% +# Import a Geometry File +# ~~~~~~~~~~~~~~~~~~~~~~ + +# sphinx_gallery_start_ignore +app.new() +# sphinx_gallery_end_ignore + +geom_file_path = download_file("Contact_Debonding_Example.agdb", "pymechanical", "embedding") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = (Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic) +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + + +# %% +# Plot and Print the Tree (To check model so far) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Plot +app.plot() + +# Print the tree +app.print_tree() + + +# %% +# Save the model +# ~~~~~~~~~~~~~~~ +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +app.save_as(test_mechdat_path) + + +# sphinx_gallery_start_ignore +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore \ No newline at end of file diff --git a/examples/setup/out/test.mechdat b/examples/setup/out/test.mechdat new file mode 100644 index 0000000000000000000000000000000000000000..c4795aaa0e90420949494b2db1ffce3373569ccf GIT binary patch literal 4766920 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 z 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 zn6@iO-CKW-<|G6N5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N 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 z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs 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 literal 0 HcmV?d00001 diff --git a/examples/setup/readme.txt b/examples/setup/readme.txt new file mode 100644 index 000000000..5769a4c43 --- /dev/null +++ b/examples/setup/readme.txt @@ -0,0 +1,4 @@ +Setup +----- + +Set up Embedding and configure From 37e5ec8b9a3691117ac8f9e1afeff8084033f4e1 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 11 Aug 2025 07:23:58 -0500 Subject: [PATCH 02/52] update order --- examples/{setup => 00_setup}/01_setup.py | 0 examples/{setup => 00_setup}/out/test.mechdat | Bin 4766920 -> 4766920 bytes examples/{setup => 00_setup}/readme.txt | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename examples/{setup => 00_setup}/01_setup.py (100%) rename examples/{setup => 00_setup}/out/test.mechdat (99%) rename examples/{setup => 00_setup}/readme.txt (100%) diff --git a/examples/setup/01_setup.py b/examples/00_setup/01_setup.py similarity index 100% rename from examples/setup/01_setup.py rename to examples/00_setup/01_setup.py diff --git a/examples/setup/out/test.mechdat b/examples/00_setup/out/test.mechdat similarity index 99% rename from examples/setup/out/test.mechdat rename to examples/00_setup/out/test.mechdat index c4795aaa0e90420949494b2db1ffce3373569ccf..aa09906c89176a3fa73d19879fae04fae0b2e48b 100644 GIT binary patch delta 11951 zcmZYFWl$Z<7ARoc-Ccr9aA)Je-Q696yAJLW9D)-F7J{=09^56kySrO}$2qs^zE}7C z_*V7I?&;Y-rdIdN>cPh%sKIwN#n8}UYgrkrXfU$%7tl|Loa_+n5Uda!5Zn;{5Nr^< z5CZSVobQnvg6I7V$9rUck8J<;_^0*W4kbm4Bt?UK2L&cYgRXpov`7(y7SBLNgQ5KI z=#Um*A2b*z1i%Ca0>T@zT}#o4Sdt)c`j7ZyM7k52kTXPit(8MHFCx|=b(3Z>4rNJv zSj(W^vi`E&N#k6C4BsO>MIZza!UT`jaSh$ef`9<&_vtu zkP~2poutj?^dtK3hfN~9&A$uE%$_R!Q@>Z1<;WE4%z$L~e6qx+!uue8rT zbV72TQYq82$ybX+R=I%!M4~H4JCf-ZbcfFVsfx+%{#=TJ(^^9I``^w?X6(6hDpK!S z9I}rAzZ?eHxMxDR=S>ge;umsos5w6~yK}t46(yYqDL*&Cf z@OoR?8Tj^!JUb~_HT$wBUPL5ibPcPo{JgBAL3OOWiXJhT4 zk!&A+mVG*G;ny6z4@+=L<4b%jdz!3!jYqhwu6@4;@rBOCie?Y;W|Bvb1eIevS8(~4 z#!6rCWC$&=nXIiICTu12>l_@unmCzqgaSixv>+UEtFP#U2QzpBY%}WMVrz_9eSnNZ zz8sx)yTBt8clzWLY8a&Vu$_t#PeBOW3JE6{Je@9h_TbJx?Xz|hn}ZAjQ@hB)ZB=wy z%~Ux}`O044cxx}5iEie}TjonV1bZjCM@8sZ|WFk8R`!LA#;wmwYQ;<+XK@PFS`bFQ-Fs}g4^Tb z-8w<4v86I`?$QOz_!WRUL+{kUGu|8c7ZfE$^CJ@juU1+U`-%;Oq&R4PS!N}Eb*yS3 z{^^FEgLa3I&k!dQ!zpH%c4yHWAicU=5E2*8t2(WtK#=PzZ8c68kq~oZs?gw-R~%i1 z__cRqtJPgs4mn0r;qaAc^rOI!Fk;%Rz;fs%E=)q_vWPdR1tv0BS~I{;g9r1`g&s+< zmp9Rl)~wPSCoAgZ4D+fs4J0lcDEM@(TyCzz328cz>PJfOJyP04hx0eqXB7MIQsF4} zv=nR#Avwk{5s#F9@8Npu{W>RY0xRTdwo&A8;RMrH7=cd_KEE*dBOY1Pq!-v(i6RHt zs)-Z3*jPyuyK0PtB5^qs(sNj#dfFmD?;-A=kPH&<;9kDh9NZz#QDhO1G$n?42m1~V zY)T9t`JA+Yn^D7zK>~#kNHYOViB8g~Ja^p$c(UhT&Ki5*B^{u}UR|$$%w? z9v+T?&M!596@?I;`RM62E_^ofZFEsckn?SHeDqA{a(5k_(ENK?Y4|xtL;~_P%W)&h z-r)5y;Kd=;(!g9KxhC@F4o(#MZ2VUEBuo2b)UMhF|7eW=GqBC;Z2xtbJ2B+o5ll3MFgB~y9Y`!~IhWqzNXsAK@Dl^UN@fGzG-m!Dk4?$yVN^@?C zs>^9bO=Q)G+%r?vXnt7P&f(1c+zU>Fj#zWeCyrzp48Aq^Yro@*FAoT4cH@kwc*a=+ z0Vli;NpCH0qfC$SOT^9RFmjwcY$?{A$ziTl^@G~XFZ@ljKZ*5B(i#H@cg=GNcuoqgnV-$#X6bvV7&o!%%0jA0#5F6DP7+|D!H zflFRH{6*@i=DYC}&RL(>`d4M66s{M6-O=%n!&Ey1KX6~0LOb`|jUp$_@%-L*x@=wRVqSmZT3iH~?$tm!g7f%J zFFNKhAah`dsQ9s=@0F*=?`4NhHz%@BYQZdfrg}?grrK=IhZ<~-ss_~ey#fN80nexY z09R#A-`umg72`eEPp`j!x5#yKjL2SQ$pg|>1GKySylAQgt&JAU$X{$Li8)SUJLK#hFK=^D2b^Q12!8)xYf_ zxNQv&JQz!Q%9aG}UCk%9IW0^28gD3{{jejk%c z*y(8lAZf3#ut|ZW*}>ZIw1@PN-tSflmj0~rN*{f~zm$tSArSg#su2dzc;jAil^(c& zqvL7zRbph(Kd1wPxG8I}|BOh=;GM1~#z5O1r|?3lt?)#qutP)ZRkfjOhf#iYu)Q`+9qa}w^Scp0^g=+@sCSGeU6`G!xQ zcQhS3dPsAZA2@>koG_4=dHZ(4K`Pf9{PW0MqMA(!8waXCAp1qWQ-9h??lHg^>on{y z*s5-$2ADlJou^QrR_C0a=8Rle{Y@pqo^^~bPxQMhqmZ+E-~u6s&!@)YDqgaaEyCqIM%AnJUmLfJm-zdR z_?L-rQe+#)X3dokpNg0K+Iaxw%G?AWC!6!$rSd#-^N9oBH9?0w#S=023C-`P$=QTw?q1v0u^Y1%Y5Pnu}H;KzbKX8pc4e|P5yUs*?IhTW`XR@ zkflH||L?>C*$aN8Kp{tjEXp8cL~(&-dtW>oM@BQEyhDA5299P#kABNgF{FS2lQ3d5 zKtUE~Ofh5pKO+=_gFj+`5rG1t_n9f@)X?v9_Pj@Ds>Mj1QPWoB=Mi=Xx?0j~taWtO zM)8=`Z#1q#Bc2&znNrcIpQMW{k~~jf#6lpT1>6ZjSU!F+dodSPF%fM)$!}U@vpA%x zrgbR-eQi)&X|I8=qm^rQG{oc*++Xn<8hH*Ve)vO$CF}q9%!_AmMzljHr?^XU=UV0e|ne+S~fZ zIrWQR4`GnRyJy?w_(0)=@ryE43BQ7?#e#EB@Fw&v3C-WXf3xg)*X$2l7V4Z&Lm!XH z14(}CTMaC-36A}&qmZw|$x(L>i0E5n&MtJ$F$}K37q9;!fI1JDe@>R9^nwys<)OLy zMCpL{b4z0wZ52f@|x|WimpAhsvxUCAx?bEE~7N z942Gc$kj7(o%siV5;5)-W%>(>3+8$FMLalT3f=I5d_fC{m2KVJXCkn{;~qj{=KVc^ zoNS~t%=7TrBB^1bs=jm+<=M`RbfWz+Bs2#H=XYn%Aez{xE14XVur>)Z2+A}syG1mS zM9Ntu!UdLL8KZKu*e_yXU4P2=Md_C`67IStwg;z-2p8x8=x57~0+ba-=tzr=C=`-3 z$ZV9G!5|4Z1CAQ$8XDsMI_<=TQt6Xt|q=Cpu<+YH&KX5NQibr$?Of$CbYjXz$2PUO97$H~s1=pYa=KE+1 zuHhza!7%h33Qx0x$MunNQHgSS6)ehH^R^pR z2Pcn3tvM%sq$d~4rZRa8O{@2jnp7v7(YSaZ;>jUV$$M9S!|8^h{^lK25~oMmuXhgH zAP70e{<00qndq8@cm@f=vZF;Ev-g^2II|H|rbBibR*PLcI(0~Cx!=E$8gBniC*)T(!l%BSo&hSY9h$Ae#fIcl zKNIcdc}`oTTRm;&Sx)r=d2H)0I2G~sc(@w@<(NAupNA)Ke$E@?L8sK0a4*?JGgcy) z7kua!UYem~^kDK{)vu2D2gqy37OZO&zAE1~VBGklwX@`(*xTClWf$rB#K&uRQu$Kr znovj+rAk>+w&vB2IJplP^f?(kKbBCYY-y?;^}aY_nt}@rq-p!gOIA{4UF;c_IT(z9 zkCuM4lKcLVGM78fLF|Hr8D4ouGiqM!Yj&-;H`$ptMOB1OEqRu!6rdW^r}B8Hjpe&o zwpJ($tAovWv!H@jv4grstoNwt>|HY&L1Py7FC8-ouF&l@2-ycCANVk0Yc3p<{U!sSo{3SGdV{(UkP$gr_t&$9@Y8xHA`zv6HR7XuY zFdn@F%SQ*f!zQQ_eOEboTU%{8Fn+U>o9$vz>Y7@C<9nkbb#1ur&$sziN^q1I2X2AJ$-`v{i7J0#_&@z}-bcpgLv(*k*5&w=bQrt!zN zr(vf2=Oye`UqZiP?a|E3#I3n2Hl*yMm9@#7{VCy(sLuWR#mzP87_dd_?^AM9FB%lCL$Boy(= z4(U{;X;Z$2Rfc(m!~tA(Y;nJ*r0X;GZSq_a_DIc7gb7OMY$IHWAjl(J)|vf#xCRKq zkNpa;_?^nfeWW-yF{gFMG5NL?2Nd@OpJk|P;Bue|gP*ok1pE7f#FG_84X8^sc*E!@ zJTx4**TNiVQHOOrLo@`g?aa3?FLyfqFZDZL=ds&Rg?%4>I{-kyRX&+_8(7yq_g;Zk z(}j%@l|!i_u(I*kOsHY}*|obslIlu5eo(#1n=`@0mKu2=7kJ%T?hI3PBgODRk1Ak8 zQ)4pGr$JC>5UxU=@0h8WdW#d1_eI#JVoD9I<_aM%jn{a`ZCa zqp~bqcG{|AnowFUlXMdhkv3|S)u$uVqNqm+3}NehQ6Ia_tenCjlB-BxfL!%E|;=hB3vNORY-Aeh)e7-Zza zc@tx83uwVUYno1f^C#jY(cw~>OhXF!i(0!L>_>!ETNV?s(L(Nwq$Wq8k)pc371>If zmi@JU#>1Kc|H_S(WEGBRb>|Dg)L6Sgzw*a?nmP!OM!^cp_$nkXBirn?^i=JQ44<$-N*qlxHWg;x3~6pud{H|3fO>TF&V~ZBFmAqne+%JQ zobVW^xT1Kz%GcjJ0C~jsXj5#j2qfC*S{h=&`ox zClK2z+TDqcm7wTJL_|unC};HXigJGjr79o$w_poA%oy70Jhb@d(lgQ!mKAtyo~t2f zXNPY}XW<~8t6lca#9{BkY4f3uWId53UahTuk|~AOrhP~ z)3wb9dF4D9q_eugog#20UlL*lak4XM?-HYh!5b*&}H@jQ=K?FGC z2*tiKCOurm^}z&Yvn*J{ff!4|2-_QAg3VsE*zJ!b0r6rC?yC+O+9WX0$8M7>#psMODPn%sYt=&?uj z%kEp_W(!6P@)65%M}4)jc=a-L`x*a%2Rwl~%7V*7#BXKAV8R|Yy%TCe8DTSyr{`5R zxUb(mux>CT2J4KA*r#b!hvjNrYJsmD-71Vpa!^w88D$yr(Do(uX+omh1>g7;74yPW zV(7OQm|?ZeyA!)E_;zz6zJz|lo_BR|z?er>4b8FI564en5*Uag@2JbA5DKa69EggA zX;o+;t{xX}|Hk#RKG{alhK$>OJhpYYALD1l9a7v6(R@MTw!Mj3Xs#a9$a)~{3mFy5 z;{%rZ1SI*&t{{Ylvk;fKEutOn8k%>miA8f*9)J<&|PWw_T`FIbSrK%d27f*K z^I6miF_dd(qKLDyq+rG*$52L+XP?jKe%d|$7oV?z9ecIn3hcy$eY{%il?&9IbKX)0 zc=88j+B_+4yG*rH&KYjCD}N6uJfC^R{Hvb|`W!7C#D0*K+DzolxcUo#SfV)I{X&H$ zBckwpvNe;x#RY`j#B=d4g`YKGQIl9wVCtmE@X1ScgQb$3vpy8wOW`65Kg1))$X*S4 zSm5o0>8kM#q-I{-hV`gSP?spxQo&;A$7QP%DzKqHb+S)! zxP{q0ratSW&TUjkW6rPtnd$b;E<@Nmvr2bJr>z!N{CnZ^U49r?B1`;L_aS{ryNKm_ zihAT|&SckYla(;mkv`Ozbu4qqR$y3`idHx{3|l*a(VUw?g%Ph>&fS_{&$afcrpjeJ z?Ku5}{sBT)&N}UEhoq`~8xOj8SsQZJt(&vYdnR%E6YugoT^N@xXXS%iG5L3y`&46A zmbaBom|K=k_zfdK%=n|q^{ku?!vs=O>bD(!T;9Xg+a;|v%ZtiiKa~&+hugEDxu}Rr zVH1a$l@Z39-2<}dClHU*i};NKCz}22Y?<{PG*pOjXQW^sJzNg!TUNWbC0V_>k2jYN z3U~y{;?cAc$+z|I0~H?iT4r$R_K6HbnFHDp{a}ZC`5F}g@e9ZB1(%i{*`kR63?|)2 z-TwOrw?o~>Mus<}yKLc2>+h25wODWd8R8{)CO&O-!J+0Qynw@Z(q-iuU{(9dtlOkN0yIq%z@&*M%D@l#i`vl``EI&Is_&q z?%Kafi~%~p`fKPn#t8`K2<^bw!Be~sR@nQycT{j${%T<&CEfcb>1ID`XAG-ZE-&(0 zgn>9Re6N^$8cTE18;oD`7{}jL%gF5U&zn@uS5vjCN92`pcl-Gd9_I{VSbU+?9dp?8 zjlY3sv2{a$)c|uZzE=Yn&1>ijCsaEf)+sZD2xu zd2Wmbq{~}xn!}oZTkB?fr@q28tzH;r52m)HkNAz-^%p(Ofr%z?s^{9x#*_D#T%@ZL zFG<_&)s26QX}+W#@Q+-^-K$k^M=-EZf=nMhNq_7b)mriVMw`m^dU*3N`0(jcK<+fe zZ^LR3tTe?Jx-ZnT^V!8A{8v-AfxfAcV`u3N;N?Le)ZKWDn=T-oV6>@6DxW5h7|VoW zweI+2m`#>akCHzmf6dKu^}(`P(5(?qRWCcx(g7^(03MJ_Ax0ljXp%;<3R1TM$1AD3^L9EV(n;pC8pf{8P1_>`w!@pYF1?M8%FY zj~>JiY1cHa;YQ;RIoS1((+cCzgC73C%m==fF)wn4DsaW|8@#LQp6iGCWw-U1AA6^& zM>>pQAW16s>Mi^#^v`W@pI!G$uvp8pZvkEW*$FmW9 z3T;-D}Tt#ObkhzGp*UH{qTABJl%mI9!o!Z)v)Ty>1M`*^!I+L z^KM$Tup!G-HAA{lq1Ina}VEyr=vCxGXlR7qvCMB+#;fh-4wGJUx?>X_(4pYQuJ|y8HZ% z9Q>d(k#-E0no#IfeXJ(pLQD3KX>gTNGk6to*ubu6uJ+*>wbY8(@ zd{*>WVR2i$WZ*Zv=exVRpr1^l?RHzZ77lNgNUE9O%_ zISZEP(;uMxlAx{-&;%U*Vp>!B+Ns-Rx22dFA6hZyb=g$geCc${4=}I2N)o(D-!@G8 zj`SE`de-=pH#`~OJHf{bu6Sp~nkk7=og$laIrcyO{50`xWWwGk}ALg2^$xWh^&iXzltJmvSOjWOnel|Cm|xaS?8yba?;y zf4>m^vmz$1XPZNOZ0ccu%ca{-aWKROz^n$(8}RcYf16>qBFbJaqmj?_!)!EH*nuG(QmwxS@pQEO$jI#&m!FBlt46zH9^Jc4)2EZMJ16xs0LP&VJP-D-<;Z4{F2MW~QN?nP3G3K98b#^PaE z7^C&@A~0Zvv>gR`*afwx!`B2jpQu3`Lv$Izbg7(g8l0d!e$t&((_P5f?ZGSNZQ9DV zpn{2tr|8iM`v_%R3Vf*-E~Hgu@I5#Q#psR^q^dw$WG$ z$zpA@qA2E;fvyL$anU^{DC+uzi0ALmub>tgbc3vm{6}JpXE0hm*U0zNtR(;BD~`30 z9FzkXZmH5oRB*6aDW$*z+C~JYE<)MWi1O4HDI4s+&~`(%4PbO_mfqVg%6LM-6l7Zr zi`7|0W(GpdN<4yQETLht;nm*%5E*Kd_EncB6Nw?x=SavV?eI!Ea$Yxx&-;B4v}mGM zL6uzu&SN-~tKlXKVJnYej@J+x2(-c%qqn3_*nwB%{wj0uK2yvZq|Gd-%^BAaUQsTg z6v3^eL4K0Zz_=}1PAk?o49bt;6H$U;Zury?q~fix2;CI^q!zkVFxuoE6T%S83LJ;! z!p?r&8-bbdeD01;T0yO_L4JxlQ}tXLWU6quP&G)S!I5oa6k?OgdGrD}ju0UtO^3x8 zdP@+HcpoqfVUqK?%)$gd&qB89LZ6g?f=De_lI6M_0qCxu$YXd#`$^Lcdgf62uyDVX zFbZ`MrZ&2ysBlYz#-z>hQaSN^{e~zOWGBMQhy{ndH_nnOdYY6&Py0YMiv$U5^)d>Q1H6R6tZezIq?uf$CW)Q#%(rmr$0jJnS&W>?1EmL z$hv$9052hG6L^RkSap8RF0Ein(c3lYBhV+upYfiSQiIgZhe8BmA!E`p`4Wd8$^v$r z7i0x8y7ZT;f8UAtn7DPhhz6gc1)XN_*C<-GSc!XpKxvtfyt0YLe;4y|R~9IK5%R=b zC&9qkf-t_1FDr*)o*fh&Z_;K}3Vep=S_n*o*X6X}Rp&a6Yg((s2NDuPVQ=o06|poopx&FI1*nGt<s}WOe*+Da~N_KjknGFAl-~-Jk|(11=Q6L5BLLv=&(n!g+`L4(}a4 zxEe%ohyhqY{Zk=p)Si$h7Q+dQ)^ZTX!Y-miNAk55LvW~G6+#d~ggu9q6oX-~^P42o zpueG)VNHL9R#R)+D`!r85joBgy$3b|U7z1^tM1=@(i*fWD&qNLSQVf0gM5^SN0b+Lp- z?$I4}H&!#lO^w}F9PRHl{(5~&Zy`{dq}RJhAtv!#phHwWXv**Os8&oor++I_wuYG8 zTV7II(4vho2?dO=AMOEU#~cwO{{Vz`$EIJduWwkUa3Jw^H$oE$gWf|vs`l5a&^QM-CB%O6 z=7&$=TuiOcv?%_^6|D`{M;C$Hww~LELC0{k9&nLA)Et;JWel^#G;a0__kzt2r&x(j zNy|nfQonIt>ze(FPNSyvxZipGPfd)iz>A^Ty5HZzYwOz|<937fFLobk)to!|jDL{5 z5|CW#k}_-&FX7Jdo^Bi`i@Y(7vs}`D3GCta^EqFT{d8}813I8+%e`RU{1}FhIDwf* z*_L(z+MLRXwNt{(qse>DL+j+8xNZcn+82@-Iu+!-+rZ0c<8W}PJD+>jC6xfRJ?|sK)<)lj)duG=5n=l z32s|T=2SN%?P>dBOstI{J$vmtQJ*)DAO2_Z69e%^hebd@``=?V|1695+AhG5-wsEx z`dIV74{hXg{Uj_VRK_Gfj(NtjBFVpdA0x??NZygYBYQ^Pkqc=BW%B7iwDQzT@Ud z7Z>VxH1BA^E-rM_FaI4O@{1GwJBD|R@0h?}oR~rX-XL+RdW^k-+HswnB%e(2ARGqHLuii0k}w16Z%&)RK^>OX+cHK4PBFZkRyaP zMh;E8Yg36#h5@bWT4CfJsqbOqLHYdJ6CVF9tgnM0lj^H{ac^`EJtX3Zt0y1l^Vs;= z)${Q=5yam+c2D_**BoNrxIBUy48Usnf>Kque?5l*&7p z9+$*0p!+xmN0??Uz4I4%`fjwt^bl?;bwkuTW|JUzYhhHYn?j@9GHbLZKKe8?Na%)3 zlT+w)sQFxWGt>(rofW0wPNTqnWMS3zz2a-{P=7%d?<4a~i*Di*$3|k=hV07c6;s=Y z?g%TOQAXaOd`yZi@l#%1eCF)*7v z?%Dk}UrMMhz@g_l^mW6D@{&fm)G;cd3A)E_c=f4~RUh-BTZ@-Tm1oXQiZqAyB>5gY zFp*gz#`<+*@f9oQQ|y}C-Z4BTg zI4ZL!w|BHa(J4Dvx(-WaH(maqm_1zfR6-V6`ab5y*MSMz3gOg1OuC}LKPjemy}IWN zCguaZel-*%=y!M4Q!fYQX^txjt4+FlYae?eOOWSo_gI;K36~|h+@NNVu(|>9!!`km zW0MV0mBb1jD@NBGq4#*q1D9#+`y`3ze=AlJzNNI7*c!{(TIMx=P-;&>Nw69I^MudU zy1#7*fm`+lvd4|Nk0*D1|8CBQNKsug^2sm*zxOg%y^6)Cmc=r$1Gg`^`$KnF>1()D z>hY@C+C(z78JDm`OZwgsSLjOog<>I4XpC9izJ30<9Bm+1oZhSIFs5^i}xfKa}hl>8+gY;V(Nb#|^8f36vc@Cx_}@iIlyX;c((ZYKrl=j&)O5|+ibP6HGXxpoe^`iI*_L=hR%v~W_h@Il}Vo;D(PEb4%aS6r%Wtr&IfVhoQ1RhV*wF`LxX=o(9txZ*7N$OmoZh_6W+{8KI&k|5j ze0MIUiq68g-{e?fYj0c>q`VE{7%rR3rjbd-h8SyzqQ?4@1kEF^2boh5ijsHznTyuz zkMrGMA1>yds#l-(C*B}UreBNx|4f#&k@=rI#uUf(pFE}<#}%m@$Ni4y9WPipj_*Gy zBQi0K?;Za;fp>!7#5BN??m2-z7u;V{!Rj%U-ZcV Z^WUE64WA;>8zkRJy^{u`H^}@#_&*xb3=IGP delta 11803 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 diff --git a/examples/setup/readme.txt b/examples/00_setup/readme.txt similarity index 100% rename from examples/setup/readme.txt rename to examples/00_setup/readme.txt From fda6a3f2abcfefd71b4fee803ef78f7caa54c87c Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 11 Aug 2025 07:25:14 -0500 Subject: [PATCH 03/52] update ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 45ebf2285..0cff3d997 100644 --- a/.gitignore +++ b/.gitignore @@ -200,6 +200,7 @@ doc/source/api/* # Examples files downloaded when building docs examples/01_basic/out/* +examples/00_setup/out/* # pymechanical-specific mylocal.ip From 1f2895f1ffd9327d0ab53bdc9dd733608767115e Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Wed, 20 Aug 2025 16:34:16 +0530 Subject: [PATCH 04/52] added overwrite --- examples/00_setup/01_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 409cf767d..3cf11094f 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -54,7 +54,7 @@ output_path = Path.cwd() / "out" test_mechdat_path = str(output_path / "test.mechdat") -app.save_as(test_mechdat_path) +app.save_as(test_mechdat_path, overwrite=True) # sphinx_gallery_start_ignore From c0a8049c276e6b1c946cbe96a00c6f20635ea927 Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Wed, 20 Aug 2025 22:57:43 +0530 Subject: [PATCH 05/52] setup - agdb changed --- examples/00_setup/01_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 3cf11094f..4f9e9d493 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -25,7 +25,7 @@ app.new() # sphinx_gallery_end_ignore -geom_file_path = download_file("Contact_Debonding_Example.agdb", "pymechanical", "embedding") +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = (Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic) geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() From 6bb5f9f13002865970be06ddf75b7d72b254197f Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Wed, 20 Aug 2025 23:34:23 +0530 Subject: [PATCH 06/52] geom in progress --- examples/00_setup/02_geometry.py | 205 +++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 examples/00_setup/02_geometry.py diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py new file mode 100644 index 000000000..9bda0cd4c --- /dev/null +++ b/examples/00_setup/02_geometry.py @@ -0,0 +1,205 @@ +""".. _ref_geometry: + +Geometry +-------- + +This section has helper scripts for Geometry +""" +# %% +# Create an embedded instance and open an existing Mechanical File +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file + +mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") +app = App(db_file=mechdat_path, globals=globals()) +print(app) + + +# %% +# Get all bodies +# ~~~~~~~~~~~~~~~~~ +body_objects = Model.Geometry.GetChildren(DataModelObjectCategory.Body, True) +# or +# bodies_objects = Model.Geometry.GetChildren(Ansys.ACT.Automation.Mechanical.Body, True) + +bodies = [body.GetGeoBody() for body in body_objects] # GeoBodyWrapper +# or +# import itertools +# nested_list = [x.Bodies for x in ExtAPI.DataModel.GeoData.Assemblies[0].AllParts] +# bodies = list(itertools.chain(*nested_list)) + +bo = body_objects[0] # Access Object Details and RMB options +b = bodies[0] # Access Geometric Properties: 'Area', 'GeoData', 'Centroid', 'Faces', etc. + +# %% +# Find Body with Largest Volume +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM + +body_names_volumes = [] +for body in body_objects: + if body.Suppressed == 0 and body.Volume: + body_names_volumes.append((body.Name, body.Volume, body.GetGeoBody().Id)) + +sorted_name_vol = sorted(body_names_volumes) +bodyname, volu, bodyid = sorted_name_vol.pop() +print(f"Unit System is: {ExtAPI.Application.ActiveUnitSystem}") +print(f"Name of the Largest Body: '{bodyname}'") +print(f"Its Volume: {round(volu.Value, 2)} {volu.Unit}") +print(f"Its id: {bodyid}") + +# %% +# Find Body by its ID +# ~~~~~~~~~~~~~~~~~~~~~~ +b2 = ExtAPI.DataModel.GeoData.GeoEntityById(bodyid) +print(f"Body Name: {b2.Name}, Body Id: {b2.Id}") + +# %% +# Find the Part that the body belongs to +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +body_name = ExtAPI.DataModel.GeoData.GeoEntityById(363).Name +part_name = ExtAPI.DataModel.GeoData.GeoEntityById(363).Part.Name +print(f"The Body named '{body_name}' belongs to the part named '{part_name}'") + +# %% +# Find Body by its ID AND print its Faces, Centroid, etc. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +body2 = ExtAPI.DataModel.GeoData.GeoEntityById(bodyid) + +face_ids = [face.Id for face in body2.Faces] +centroids_of_each_face = [ + ExtAPI.DataModel.GeoData.GeoEntityById(face_id).Centroid for face_id in face_ids +] +for face_id, centroid in zip(face_ids, centroids_of_each_face): + print(face_id, list(centroid)) + +# %% +# Get all Vertices +# ~~~~~~~~~~~~~~~~~~~ +vertices = [] +geo = ExtAPI.DataModel.GeoData +for asm in geo.Assemblies: + for part in asm.Parts: + for body in part.Bodies: + for i in range(0, body.Vertices.Count): + vertices.append(body.Vertices[i].Id) + +print(vertices) + +# %% +# Get all edges of a given length +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM +use_length = 75 + +geo = ExtAPI.DataModel.GeoData +edgelist = [] + +for asm in geo.Assemblies: + for part in asm.Parts: + for body in part.Bodies: + for edge in body.Edges: + if abs(edge.Length - use_length) <= use_length * 0.01: + edgelist.append(edge.Id) +print(edgelist) + +# %% +# Get all circular edges of a given radius +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import math + +radius = 10 +circumference = 2 * math.pi * radius + +geo = ExtAPI.DataModel.GeoData +circlelist = [] + +for asm in geo.Assemblies: + for part in asm.Parts: + for body in part.Bodies: + for edge in body.Edges: + if ( + abs(edge.Length - circumference) <= circumference * 0.01 + and str(edge.CurveType) == "GeoCurveCircle" + ): + circlelist.append(edge.Id) +print(circlelist) + +# %% +# Get Radius of a selected edge +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +my_edge = ExtAPI.DataModel.GeoData.GeoEntityById(185) +my_edge_radius = my_edge.Radius if str(my_edge.CurveType) == "GeoCurveCircle" else 0.0 +print(my_edge_radius) + +# %% +# Create a Named Selection from a list of body Ids +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +mylist = [bodyid] + +selection_manager = ExtAPI.SelectionManager +selection = ExtAPI.SelectionManager.CreateSelectionInfo( + SelectionTypeEnum.GeometryEntities +) +selection.Ids = mylist +selection_manager.NewSelection(selection) + +ns2 = ExtAPI.DataModel.Project.Model.AddNamedSelection() +ns2.Name = "bodies2" +ns2.Location = selection + +# %% +# Find a Named Selection with a prefix +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) +my_nsel = [i for i in NSall if i.Name.startswith("b")][0] +print(my_nsel.Name) + +# %% +# Create a Named Selection of all bodies with a cylindrical face +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +geo = ExtAPI.DataModel.GeoData +cyl_body_ids = [] + +for asm in geo.Assemblies: + for part in asm.Parts: + for body in part.Bodies: + countcyl = 0 + for face in body.Faces: + if ( + face.SurfaceType + == Ansys.ACT.Interfaces.Geometry.GeoSurfaceTypeEnum.GeoSurfaceCylinder + ): + countcyl = countcyl + 1 + if countcyl != 0: + cyl_body_ids.append(body.Id) + +selection_manager = ExtAPI.SelectionManager +selection = ExtAPI.SelectionManager.CreateSelectionInfo( + SelectionTypeEnum.GeometryEntities +) +selection.Ids = cyl_body_ids + +model = ExtAPI.DataModel.Project.Model +ns2 = model.AddNamedSelection() +ns2.Name = "bodies_with_cyl_face" +ns2.Location = selection +selection_manager.ClearSelection() + +# %% +# Modify material assignment +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +allbodies = ExtAPI.DataModel.Project.Model.GetChildren( + DataModelObjectCategory.Body, True +) +for body in allbodies: + body.Material = "Structural Steel" + +# %% +# Get all Coordinate Systems +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +tree_CS = ExtAPI.DataModel.Project.Model.CoordinateSystems \ No newline at end of file From 909b5000787eb748157e83736caa4c190fef2249 Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Thu, 21 Aug 2025 07:39:08 +0530 Subject: [PATCH 07/52] geometry with new model --- examples/00_setup/02_geometry.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 9bda0cd4c..eca226607 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -5,16 +5,23 @@ This section has helper scripts for Geometry """ -# %% -# Create an embedded instance and open an existing Mechanical File -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file +app = App(globals=globals()) +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + +# Plot +app.plot() -mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") -app = App(db_file=mechdat_path, globals=globals()) -print(app) # %% @@ -59,8 +66,8 @@ # %% # Find the Part that the body belongs to # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -body_name = ExtAPI.DataModel.GeoData.GeoEntityById(363).Name -part_name = ExtAPI.DataModel.GeoData.GeoEntityById(363).Part.Name +body_name = ExtAPI.DataModel.GeoData.GeoEntityById(59).Name +part_name = ExtAPI.DataModel.GeoData.GeoEntityById(59).Part.Name print(f"The Body named '{body_name}' belongs to the part named '{part_name}'") # %% @@ -85,14 +92,13 @@ for body in part.Bodies: for i in range(0, body.Vertices.Count): vertices.append(body.Vertices[i].Id) - print(vertices) # %% # Get all edges of a given length # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM -use_length = 75 +use_length = 0.100 geo = ExtAPI.DataModel.GeoData edgelist = [] @@ -110,7 +116,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import math -radius = 10 +radius = 0.018 circumference = 2 * math.pi * radius geo = ExtAPI.DataModel.GeoData @@ -130,7 +136,7 @@ # %% # Get Radius of a selected edge # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -my_edge = ExtAPI.DataModel.GeoData.GeoEntityById(185) +my_edge = ExtAPI.DataModel.GeoData.GeoEntityById(27) my_edge_radius = my_edge.Radius if str(my_edge.CurveType) == "GeoCurveCircle" else 0.0 print(my_edge_radius) From 09f6407f140bcd9d664e050b7af5022b6a2230ea Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Thu, 21 Aug 2025 08:38:59 +0530 Subject: [PATCH 08/52] started connections page --- examples/00_setup/02_geometry.py | 4 + examples/00_setup/03_connections.py | 120 ++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 examples/00_setup/03_connections.py diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index eca226607..6c220983c 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -6,6 +6,10 @@ This section has helper scripts for Geometry """ +# %% +# Import Geometry +# ~~~~~~~~~~~~~~~ + from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file app = App(globals=globals()) diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py new file mode 100644 index 000000000..a0167760a --- /dev/null +++ b/examples/00_setup/03_connections.py @@ -0,0 +1,120 @@ +""".. _ref_connections: + +Connections +----------- + +This section has helper scripts for Connections. +""" + + +# sphinx_gallery_start_ignore +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file + +app = App(globals=globals()) +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) +# sphinx_gallery_end_ignore + +app.plot() + + +# %% +# Get information about all Contacts Defined +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +all_contacts = ExtAPI.DataModel.Project.Model.Connections.GetChildren( + DataModelObjectCategory.ContactRegion, True +) +for contact in all_contacts: + print( + f"\n{contact.Parent.Name} > {contact.Name} : {contact.ContactType} : {contact.Suppressed} : {contact.ContactFormulation}" + ) + print("Contact: ", contact.ContactBodies, list(contact.SourceLocation.Ids)) + print("Target: ", contact.TargetBodies, list(contact.TargetLocation.Ids)) + +# %% +# Insert a Joint using face IDs +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +face1 = 44 +face2 = 251 + +model = ExtAPI.DataModel.Project.Model +j = model.Connections.AddJoint() + +reference_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +reference_scoping.Ids = [face1] +j.ReferenceLocation = reference_scoping + +mobile_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +mobile_scoping.Ids = [face2] +j.MobileLocation = mobile_scoping + +# %% +# Create Automatic Connections on a chosen named selection +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +contactgroup = ExtAPI.DataModel.Project.Model.Connections.AddConnectionGroup() +contactgroup.FaceFace = True +contactgroup.FaceEdge = contactgroup.FaceEdge.No +contactgroup.GroupBy = contactgroup.GroupBy.Faces +contactgroup.Priority = contactgroup.Priority.FaceOverEdge +contactgroup.InternalObject.DetectCylindricalFacesType = 1 + +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) +my_nsel = [i for i in NSall if i.Name == "bodies3"][0] + +contactgroup.Location = my_nsel +contactgroup.CreateAutomaticConnections() + +mytree = ExtAPI.DataModel.Tree +mytree.Refresh() + +# %% +# Create a Contact region using face named selections +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +c = ExtAPI.DataModel.Project.Model.Connections +c1 = c.AddContactRegion() +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) +a = [i for i in NSall if i.Name == "faces_tube"][0] +c1.TargetLocation = a +a = [i for i in NSall if i.Name == "faces_bracket"][0] +c1.SourceLocation = a + +# %% +# Define a Bearing +# ~~~~~~~~~~~~~~~~ +brg = ExtAPI.DataModel.Project.Model.Connections.AddBearing() +brg.ReferenceRotationPlane = RotationPlane.XY +brg.StiffnessK11.Output.DiscreteValues = [Quantity("11 [N/m]")] +brg.StiffnessK22.Output.DiscreteValues = [Quantity("22 [N/m]")] +brg.StiffnessK21.Output.DiscreteValues = [Quantity("21 [N/m]")] +brg.StiffnessK12.Output.DiscreteValues = [Quantity("12 [N/m]")] + +brg.DampingC11.Output.DiscreteValues = [Quantity("111 [N sec m^-1]")] +brg.DampingC22.Output.DiscreteValues = [Quantity("122 [N sec m^-1]")] +brg.DampingC12.Output.DiscreteValues = [Quantity("112 [N sec m^-1]")] +brg.DampingC21.Output.DiscreteValues = [Quantity("121 [N sec m^-1]")] + +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) +brg.ReferenceLocation = [i for i in NSall if i.Name == "f1"][0] +brg.MobileLocation = [i for i in NSall if i.Name == "f2"][0] + + +# sphinx_gallery_start_ignore +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore From fcc1b9436131757700d60a312f43c58e247c310a Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Thu, 21 Aug 2025 12:07:22 +0530 Subject: [PATCH 09/52] connections done --- examples/00_setup/02_geometry.py | 2 + examples/00_setup/03_connections.py | 58 ++++++++++++++++++----------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 6c220983c..2aced82dc 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -26,6 +26,8 @@ # Plot app.plot() +# Print the tree +app.print_tree() # %% diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index a0167760a..ca8dc6eae 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -6,7 +6,6 @@ This section has helper scripts for Connections. """ - # sphinx_gallery_start_ignore from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file @@ -25,6 +24,8 @@ app.plot() +# Print the tree +app.print_tree() # %% # Get information about all Contacts Defined @@ -39,22 +40,6 @@ print("Contact: ", contact.ContactBodies, list(contact.SourceLocation.Ids)) print("Target: ", contact.TargetBodies, list(contact.TargetLocation.Ids)) -# %% -# Insert a Joint using face IDs -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -face1 = 44 -face2 = 251 - -model = ExtAPI.DataModel.Project.Model -j = model.Connections.AddJoint() - -reference_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -reference_scoping.Ids = [face1] -j.ReferenceLocation = reference_scoping - -mobile_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -mobile_scoping.Ids = [face2] -j.MobileLocation = mobile_scoping # %% # Create Automatic Connections on a chosen named selection @@ -69,7 +54,7 @@ NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) -my_nsel = [i for i in NSall if i.Name == "bodies3"][0] +my_nsel = [i for i in NSall if i.Name == "bodies_5"][0] contactgroup.Location = my_nsel contactgroup.CreateAutomaticConnections() @@ -85,11 +70,35 @@ NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) -a = [i for i in NSall if i.Name == "faces_tube"][0] +a = [i for i in NSall if i.Name == "block1_washer_cont"][0] c1.TargetLocation = a -a = [i for i in NSall if i.Name == "faces_bracket"][0] +a = [i for i in NSall if i.Name == "block1_washer_targ"][0] c1.SourceLocation = a + +# %% +# Insert a Joint using face IDs +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +face1 = 135 +face2 = 160 + +from pathlib import Path # delete +output_path = Path.cwd() / "out" # delete +test_mechdat_path = str(output_path / "temporarycheck.mechdat") # delete +app.save_as(test_mechdat_path, overwrite=True) # delete + + +model = ExtAPI.DataModel.Project.Model +j = model.Connections.AddJoint() + +reference_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +reference_scoping.Ids = [face1] +j.ReferenceLocation = reference_scoping + +mobile_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +mobile_scoping.Ids = [face2] +j.MobileLocation = mobile_scoping + # %% # Define a Bearing # ~~~~~~~~~~~~~~~~ @@ -108,8 +117,8 @@ NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) -brg.ReferenceLocation = [i for i in NSall if i.Name == "f1"][0] -brg.MobileLocation = [i for i in NSall if i.Name == "f2"][0] +brg.ReferenceLocation = [i for i in NSall if i.Name == "shank_surface"][0] +brg.MobileLocation = [i for i in NSall if i.Name == "shank_surface"][0] # sphinx_gallery_start_ignore @@ -118,3 +127,8 @@ # Delete the downloaded files delete_downloads() # sphinx_gallery_end_ignore + + +# %% +# TODO : Change Model for Joint and Bearing +# ~~~~~~~~~~~~~~~~ \ No newline at end of file From a034c2fd49d17578560fa4892708c01aef8a82bc Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Thu, 21 Aug 2025 15:20:25 +0530 Subject: [PATCH 10/52] nsel ready --- examples/00_setup/02_geometry.py | 18 ++- examples/00_setup/03_connections.py | 8 ++ examples/00_setup/04_named_selections.py | 148 +++++++++++++++++++++++ examples/00_setup/05_mesh.py | 50 ++++++++ examples/00_setup/06_results.py | 47 +++++++ examples/00_setup/07_tree_objects.py | 50 ++++++++ 6 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 examples/00_setup/04_named_selections.py create mode 100644 examples/00_setup/05_mesh.py create mode 100644 examples/00_setup/06_results.py create mode 100644 examples/00_setup/07_tree_objects.py diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 2aced82dc..02e30dcde 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -214,4 +214,20 @@ # %% # Get all Coordinate Systems # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -tree_CS = ExtAPI.DataModel.Project.Model.CoordinateSystems \ No newline at end of file +tree_CS = ExtAPI.DataModel.Project.Model.CoordinateSystems + + +# sphinx_gallery_start_ignore +# Save the mechdat +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +# app.save_as(test_mechdat_path, overwrite=True) + + +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index ca8dc6eae..b02ca556e 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -122,6 +122,14 @@ # sphinx_gallery_start_ignore +# Save the mechdat +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +# app.save_as(test_mechdat_path, overwrite=True) + + # Close the app app.close() # Delete the downloaded files diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py new file mode 100644 index 000000000..299d9a613 --- /dev/null +++ b/examples/00_setup/04_named_selections.py @@ -0,0 +1,148 @@ +""".. _ref_named_selections: + +Named Selections +---------------- + +This section has helper scripts for Named Selections. +""" + +# %% +# Import Geometry +# ~~~~~~~~~~~~~~~ + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file +app = App(globals=globals()) +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + +# Plot +app.plot() + +# Print the tree +app.print_tree() + + + +# %% +# Fetch all Named Selections +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# ALL NAMED SELECTIONS +nsall = ExtAPI.DataModel.GetObjectsByType( + DataModelObjectCategory.NamedSelections.NamedSelection +) + +# %% +# Delete a named selection +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) + +# Delete a named selection by name +a = [i for i in NSall if i.Name == "S1"][0] +a.Delete() + +# Alternative way to delete by name +b = ExtAPI.DataModel.Tree.GetObjectsByName("S1")[0] +b.Delete() + +# %% +# Create a named selection +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +selection_manager = ExtAPI.SelectionManager +selection = ExtAPI.SelectionManager.CreateSelectionInfo( + SelectionTypeEnum.GeometryEntities +) +selection.Ids = [1, 2, 3, 4] + +model = ExtAPI.DataModel.Project.Model +ns2 = model.AddNamedSelection() +ns2.Name = "faces" +ns2.Location = selection +selection_manager.ClearSelection() + +# %% +# Create a Named Selection by Worksheet +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NS1 = DataModel.Project.Model.AddNamedSelection() +NS1.ScopingMethod = GeometryDefineByType.Worksheet +GenerationCriteria = NS1.GenerationCriteria + +Criterion1 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +Criterion1.Action = SelectionActionType.Add +Criterion1.EntityType = SelectionType.GeoFace +Criterion1.Criterion = SelectionCriterionType.LocationY +Criterion1.Operator = SelectionOperatorType.Equal +Criterion1.Value = Quantity("0 [m]") +GenerationCriteria.Add(Criterion1) + +Criterion2 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +Criterion2.Action = SelectionActionType.Add +Criterion2.EntityType = SelectionType.GeoFace +Criterion2.Criterion = SelectionCriterionType.LocationZ +Criterion2.Operator = SelectionOperatorType.Equal +Criterion2.Value = Quantity("0 [m]") +GenerationCriteria.Add(Criterion2) + +NS1.Generate() + +# %% +# Find a Named Selection +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) + +# Find a named selection by name +a = [i for i in NSall if i.Name == "bodies2"][0] + +# Access entities in the named selection +entities = a.Entities +print(entities) + +# %% +# Identify Named Selections based on Name and Type +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) + +# Filter named selections based on keywords in their names +keywords = ["fix", "bushing", "roller"] +ns1 = [i for i in NSall if keywords[0] in i.Name] +ns2 = [i for i in NSall if keywords[1] in i.Name] +ns3 = [i for i in NSall if keywords[2] in i.Name] +filtered = ns1 + ns2 + ns3 + +# Further filter based on entity type +VertexNsels = [ + i + for i in filtered + if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoVertex" +] + + + +# sphinx_gallery_start_ignore +# Save the mechdat +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +app.save_as(test_mechdat_path, overwrite=True) + + +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore diff --git a/examples/00_setup/05_mesh.py b/examples/00_setup/05_mesh.py new file mode 100644 index 000000000..7ce201b57 --- /dev/null +++ b/examples/00_setup/05_mesh.py @@ -0,0 +1,50 @@ +""".. _ref_mesh: + +Mesh +---- + +This section has helper scripts for Named Selections. +""" + + +# %% +# Import Geometry +# ~~~~~~~~~~~~~~~ + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file +app = App(globals=globals()) +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + +# Plot +app.plot() + +# Print the tree +app.print_tree() + + + + + +# sphinx_gallery_start_ignore +# Save the mechdat +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +# app.save_as(test_mechdat_path, overwrite=True) + + +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore diff --git a/examples/00_setup/06_results.py b/examples/00_setup/06_results.py new file mode 100644 index 000000000..13074c482 --- /dev/null +++ b/examples/00_setup/06_results.py @@ -0,0 +1,47 @@ +""".. _ref_results: + +Results +------- + +This section has helper scripts for Results. +""" + +# %% +# Import Geometry +# ~~~~~~~~~~~~~~~ + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file + +app = App(globals=globals()) +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + +# Plot +app.plot() + +# Print the tree +app.print_tree() + + +# sphinx_gallery_start_ignore +# Save the mechdat +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +# app.save_as(test_mechdat_path, overwrite=True) + + +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore diff --git a/examples/00_setup/07_tree_objects.py b/examples/00_setup/07_tree_objects.py new file mode 100644 index 000000000..e1574c3b1 --- /dev/null +++ b/examples/00_setup/07_tree_objects.py @@ -0,0 +1,50 @@ +""".. _ref_tree_objects: + +Tree Objects +------------ + +This section has helper scripts for Tree Objects. +""" + + +# %% +# Import Geometry +# ~~~~~~~~~~~~~~~ + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file +app = App(globals=globals()) +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + +# Plot +app.plot() + +# Print the tree +app.print_tree() + + + + + +# sphinx_gallery_start_ignore +# Save the mechdat +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +# app.save_as(test_mechdat_path, overwrite=True) + + +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore From 0377c050b34ecfe6a79cf20e4ab777006b9af58c Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Fri, 22 Aug 2025 00:15:22 +0530 Subject: [PATCH 11/52] results done --- examples/00_setup/04_named_selections.py | 44 +++----- examples/00_setup/05_mesh.py | 72 +++++++++++-- examples/00_setup/06_results.py | 127 ++++++++++++++++++++--- 3 files changed, 196 insertions(+), 47 deletions(-) diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index 299d9a613..0c0cce210 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -6,14 +6,13 @@ This section has helper scripts for Named Selections. """ -# %% -# Import Geometry -# ~~~~~~~~~~~~~~~ + +# sphinx_gallery_start_ignore from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file app = App(globals=globals()) -geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geom_file_path = download_file("example_05_td26_Rubber_Boot_Seal.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() @@ -22,6 +21,7 @@ geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) +# sphinx_gallery_end_ignore # Plot app.plot() @@ -36,33 +36,27 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ALL NAMED SELECTIONS -nsall = ExtAPI.DataModel.GetObjectsByType( - DataModelObjectCategory.NamedSelections.NamedSelection -) +nsall = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.NamedSelections.NamedSelection) # %% # Delete a named selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) # Delete a named selection by name -a = [i for i in NSall if i.Name == "S1"][0] +a = [i for i in NSall if i.Name == "Top_Face"][0] a.Delete() # Alternative way to delete by name -b = ExtAPI.DataModel.Tree.GetObjectsByName("S1")[0] +b = ExtAPI.DataModel.GetObjectsByName("Bottom_Face")[0] b.Delete() # %% # Create a named selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ selection_manager = ExtAPI.SelectionManager -selection = ExtAPI.SelectionManager.CreateSelectionInfo( - SelectionTypeEnum.GeometryEntities -) -selection.Ids = [1, 2, 3, 4] +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection.Ids = [216,221,224] model = ExtAPI.DataModel.Project.Model ns2 = model.AddNamedSelection() @@ -98,36 +92,32 @@ # %% # Find a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) # Find a named selection by name -a = [i for i in NSall if i.Name == "bodies2"][0] +a = [i for i in NSall if i.Name == "Rubber_Bodies30"][0] # Access entities in the named selection entities = a.Entities -print(entities) +print(entities[0].Volume) # %% # Identify Named Selections based on Name and Type # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) # Filter named selections based on keywords in their names -keywords = ["fix", "bushing", "roller"] +keywords = ["Rubber_Bodies30", "Inner_Faces30","Outer_Faces30"] ns1 = [i for i in NSall if keywords[0] in i.Name] ns2 = [i for i in NSall if keywords[1] in i.Name] ns3 = [i for i in NSall if keywords[2] in i.Name] filtered = ns1 + ns2 + ns3 # Further filter based on entity type -VertexNsels = [ +FaceNsels = [ i for i in filtered - if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoVertex" + if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" ] diff --git a/examples/00_setup/05_mesh.py b/examples/00_setup/05_mesh.py index 7ce201b57..ca1b0f5ea 100644 --- a/examples/00_setup/05_mesh.py +++ b/examples/00_setup/05_mesh.py @@ -6,13 +6,10 @@ This section has helper scripts for Named Selections. """ - -# %% -# Import Geometry -# ~~~~~~~~~~~~~~~ - +# sphinx_gallery_start_ignore from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file + app = App(globals=globals()) geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() @@ -23,6 +20,8 @@ geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) +# sphinx_gallery_end_ignore + # Plot app.plot() @@ -31,7 +30,68 @@ app.print_tree() +# %% +# Insert a Local Meshing Control for a Named Selection +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +use_nsel = [i for i in NSall if i.Name == "shank"][0] + +ms = Model.Mesh.AddAutomaticMethod() +ms.Location = use_nsel +ms.Method = ms.Method.AllTriAllTet +ms.Algorithm = ms.Algorithm.PatchConforming + + +# %% +# Generate Mesh +# ~~~~~~~~~~~~~ +Model.Mesh.GenerateMesh() +print(Model.Mesh.ObjectState) + + +# %% +# Get Element Count of a meshed body +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +meshdata = DataModel.MeshDataByName("Global") +print(use_nsel.Ids[0]) +geoBody = DataModel.GeoData.GeoEntityById(use_nsel.Ids[0]) +body = Model.Geometry.GetBody(geoBody) +meshregion = meshdata.MeshRegionById(geoBody.Id) +print(body.Name, meshregion.ElementCount) + + +# sphinx_gallery_start_ignore +Model.Mesh.ClearGeneratedData() +# sphinx_gallery_end_ignore + + +# %% +# Insert a Sweep Method (Scoping Method: Named Selection) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +use_nsel = [i for i in NSall if i.Name == "bodies_5"][0] + +mesh = Model.Mesh +mesh_method = mesh.AddAutomaticMethod() +mesh_method.Location = use_nsel +mesh_method.Method = MethodType.Sweep + +# %% +# Insert a Mesh Sizing Control (Scoping Method: Geometry Selection) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +ns = [i for i in NSall if "bottom_surface" in i.Name][0] + +bot_face = DataModel.GeoData.GeoEntityById(ns.Ids[0]) +body_ids = [edge.Id for edge in bot_face.Edges] +sel = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +sel.Ids = body_ids +mesh = Model.Mesh +mesh_sizing = mesh.AddSizing() +mesh_sizing.Location = sel +mesh_sizing.Behavior = SizingBehavior.Hard # sphinx_gallery_start_ignore @@ -39,7 +99,7 @@ from pathlib import Path output_path = Path.cwd() / "out" -test_mechdat_path = str(output_path / "test.mechdat") +test_mechdat_path = str(output_path / "test5.mechdat") # app.save_as(test_mechdat_path, overwrite=True) diff --git a/examples/00_setup/06_results.py b/examples/00_setup/06_results.py index 13074c482..b580b4e41 100644 --- a/examples/00_setup/06_results.py +++ b/examples/00_setup/06_results.py @@ -6,23 +6,20 @@ This section has helper scripts for Results. """ -# %% -# Import Geometry -# ~~~~~~~~~~~~~~~ +# sphinx_gallery_start_ignore +import os from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file -app = App(globals=globals()) -geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") -geometry_import = Model.GeometryImportGroup.AddGeometryImport() -geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic -geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() -geometry_import_preferences.ProcessLines = True -geometry_import_preferences.NamedSelectionKey = "" -geometry_import_preferences.ProcessNamedSelections = True -geometry_import_preferences.ProcessMaterialProperties = True -geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) +mechdat_path = download_file("example_03_simple_bolt_new.mechdat", "pymechanical", "00_basic") +app = App(db_file = mechdat_path, globals=globals()) +print(app) + + +# sphinx_gallery_end_ignore + + # Plot app.plot() @@ -30,6 +27,108 @@ # Print the tree app.print_tree() +# %% +# Solve +# ~~~~~ +static_struct = app.DataModel.AnalysisList[0] +static_struct.Solution.ClearGeneratedData() +print("Solution Status:", static_struct.Solution.Status) + +static_struct.Solution.Solve() +print("Solution Status:", static_struct.Solution.Status) + + +# %% +# Results that are accessible for GetResult +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +result_names = static_struct.GetResultsData().ResultNames +print("Available Results:", ", ".join(result_names)) + + +# %% +# List Result Objects that can be added +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +all_results = [x for x in dir(static_struct) if str(x)[:3]=="Add"] +print(all_results) + +# %% +# Insert a Result +# ~~~~~~~~~~~~~~~ + + +total_deformation = static_struct.Solution.AddTotalDeformation() +total_deformation.EvaluateAllResults() + + +# %% Access max and min of a result +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +minimum_deformation = total_deformation.Minimum +maximum_deformation = total_deformation.Maximum +print(f"Minimum Deformation: {minimum_deformation}") +print(f"Maximum Deformation: {maximum_deformation}") + +# %% +# Get Results by Node Number +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +node_number = 2000 +result_data = static_struct.GetResultsData() +node_values = result_data.GetResult("U").GetNodeValues(node_number) +print(f"Node {node_number} Values:", node_values) + +# %% +# Access other results +# ~~~~~~~~~~~~~~~~~~~~ + + +# Insert a command object +cs = static_struct.Solution.AddCommandSnippet() + +# %% +# Fatigue Results +# ~~~~~~~~~~~~~~~ +solution = static_struct.Solution +fatigue_tool = solution.AddFatigueTool() + +safety_factor = fatigue_tool.AddSafetyFactor() +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.MeshNodes) +selection.Ids = [1, 2] +safety_factor.Location = selection +minimum = safety_factor.Minimum +print("Safety Factor Minimum:", minimum) + +# Export safety factor to a text file +fname = "safety_factor_results.txt" +safety_factor.ExportToTextFile(True, fname) + +# %% +# User-defined Result +# ~~~~~~~~~~~~~~~~~~~ +user_result = static_struct.Solution.AddUserDefinedResult() +print("User-defined Result Added:", user_result) + +# %% +# Get number of result sets +# ~~~~~~~~~~~~~~~~~~~~~~~~~ +reader = static_struct.GetResultsData() +result_set_count = reader.ListTimeFreq.Count +print("Number of Result Sets:", result_set_count) + + + +# %% +# Export all results in the tree to PNG (2D image) files +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +results = DataModel.GetObjectsByType(DataModelObjectCategory.Result) +for result in results: + result.Activate() + Graphics.Camera.SetSpecificViewOrientation(ViewOrientationType.Front) + image_path = os.path.join(os.getcwd(),"out",result.Name+".png") + Graphics.ExportImage(str(image_path), GraphicsImageExportFormat.PNG, Ansys.Mechanical.Graphics.GraphicsImageExportSettings()) +print("Done with Exporting Results") + + # sphinx_gallery_start_ignore # Save the mechdat @@ -43,5 +142,5 @@ # Close the app app.close() # Delete the downloaded files -delete_downloads() +# delete_downloads() # sphinx_gallery_end_ignore From 404cc5f469d260c7337cfbd1c6487b82023f7a69 Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Fri, 22 Aug 2025 00:22:09 +0530 Subject: [PATCH 12/52] started tree objects --- examples/00_setup/07_tree_objects.py | 130 ++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 4 deletions(-) diff --git a/examples/00_setup/07_tree_objects.py b/examples/00_setup/07_tree_objects.py index e1574c3b1..db9febbe1 100644 --- a/examples/00_setup/07_tree_objects.py +++ b/examples/00_setup/07_tree_objects.py @@ -7,14 +7,12 @@ """ -# %% -# Import Geometry -# ~~~~~~~~~~~~~~~ +# sphinx_gallery_start_ignore from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file app = App(globals=globals()) -geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geom_file_path = download_file("Valve.pmdb", "pymechanical", "embedding") geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() @@ -23,6 +21,8 @@ geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) +# sphinx_gallery_end_ignore + # Plot app.plot() @@ -32,6 +32,128 @@ +# %% +# Accessing Geometry +# ~~~~~~~~~~~~~~~~~~ +# Example of accessing geometry by ID. + +body = ExtAPI.DataModel.GeoData.GeoEntityById(312) + +# %% +# Accessing Mesh Data +# ~~~~~~~~~~~~~~~~~~~~~~ +# Example of accessing mesh data by name. + +node = ExtAPI.DataModel.MeshDataByName("Global").NodeById(555) +element = ExtAPI.DataModel.MeshDataByName("Global").ElementById(444) + +# %% +# Accessing All Objects and Child Objects +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Examples of accessing all objects, bodies, named selections, and contact regions. + +# All tree objects +AllObj = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.DataModelObject, True) + +# All bodies +all_bodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) + +# All named selections +ns_all = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.NamedSelections.NamedSelection) + +# All contact regions +abc = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.ContactRegion) +all_contacts = ExtAPI.DataModel.Project.Model.Connections.GetChildren(DataModelObjectCategory.ContactRegion, True) + +# A specific contact region +my_contact = [contact for contact in all_contacts if contact.Name == "Contact Region"][0] + +# All result objects of a specific type +all_norm_stress = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.Result.NormalStress) + +# Other examples +all_remote_points = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.RemotePoint) +ana = ExtAPI.DataModel.Tree.GetObjectsByType(DataModelObjectCategory.Analysis) + +# Using ACT Automation API +all_contacts2 = ExtAPI.DataModel.Project.Model.Connections.GetChildren[Ansys.ACT.Automation.Mechanical.Connections.ContactRegion](True) +all_remote_points2 = ExtAPI.DataModel.Project.Model.GetChildren[Ansys.ACT.Automation.Mechanical.RemotePoint](True) +all_folders = ExtAPI.DataModel.Project.Model.GetChildren[Ansys.ACT.Automation.Mechanical.TreeGroupingFolder](True) + +# %% +# Finding Duplicate Objects by Name +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Example of finding duplicate objects by name. + +import collections + +AllObj = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.DataModelObject, True) +AllObjNames = [x.Name for x in AllObj] +duplicates_by_name = [item for item, count in collections.Counter(AllObjNames).items() if count > 1] +print(duplicates_by_name) + +# %% +# Using DataObjects and GetByName +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Example of using DataObjects and GetByName. + +c1 = 'Solution' +c2 = 'Far-field Sound Power Level Waterfall Diagram' +c = ExtAPI.DataModel.AnalysisList[0].DataObjects.GetByName(c1).DataObjects.GetByName(c2) + +# %% +# Using DataObjects, NamesByType, and GetByName +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Example of using DataObjects, NamesByType, and GetByName. + +new_contact_list = [] +dataobjects = ExtAPI.DataModel.AnalysisList[0].DataObjects +for group in dataobjects: + print(group.Type) +names = dataobjects.NamesByType('ContactGroup') +for name in names: + connet_data_objects = dataobjects.GetByName(name).DataObjects + c_names = connet_data_objects.Names + for c_name in c_names: + type_c = connet_data_objects.GetByName(c_name).Type + if type_c == 'ConnectionGroup': + contacts_list = connet_data_objects.GetByName(c_name).DataObjects.NamesByType('ContactRegion') + for contact in contacts_list: + contact_type = connet_data_objects.GetByName(c_name).DataObjects.GetByName(contact).PropertyValue('ContactType') + contact_state = connet_data_objects.GetByName(c_name).DataObjects.GetByName(contact).PropertyValue("Suppressed") + if contact_state == 0 and contact_type == 1: + new_contact_list.append(contact) +print(new_contact_list) + +# %% +# Using GetObjectsByName +# ~~~~~~~~~~~~~~~~~~~~~~~~~ +# Example of using GetObjectsByName. + +bb = ExtAPI.DataModel.GetObjectsByName("Gray Cast Iron")[0] + +# %% +# Accessing a Named Selection +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Example of accessing a named selection. + +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +my_nsel = [i for i in NSall if i.Name.startswith("b")][0] +my_nsel2 = [i for i in NSall if i.Name == "aaa"][0] + +# %% +# Get All Unsuppressed Bodies and Point Masses +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Example of getting all unsuppressed bodies and point masses. + +all_bodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) +all_bodies = [i for i in all_bodies if not i.Suppressed] +print(len(all_bodies)) + +all_pm = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.PointMass, True) +all_pm = [i for i in all_pm if not i.Suppressed] + + # sphinx_gallery_start_ignore From d10343c152837d8b2011d1ec557f6bfb830c69af Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Fri, 22 Aug 2025 00:34:59 +0530 Subject: [PATCH 13/52] tree objects done --- examples/00_setup/07_tree_objects.py | 65 +++++++++++++++++++--------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/examples/00_setup/07_tree_objects.py b/examples/00_setup/07_tree_objects.py index db9febbe1..cc92eb3e8 100644 --- a/examples/00_setup/07_tree_objects.py +++ b/examples/00_setup/07_tree_objects.py @@ -6,11 +6,10 @@ This section has helper scripts for Tree Objects. """ - - # sphinx_gallery_start_ignore from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file + app = App(globals=globals()) geom_file_path = download_file("Valve.pmdb", "pymechanical", "embedding") geometry_import = Model.GeometryImportGroup.AddGeometryImport() @@ -31,7 +30,6 @@ app.print_tree() - # %% # Accessing Geometry # ~~~~~~~~~~~~~~~~~~ @@ -63,7 +61,9 @@ # All contact regions abc = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.ContactRegion) -all_contacts = ExtAPI.DataModel.Project.Model.Connections.GetChildren(DataModelObjectCategory.ContactRegion, True) +all_contacts = ExtAPI.DataModel.Project.Model.Connections.GetChildren( + DataModelObjectCategory.ContactRegion, True +) # A specific contact region my_contact = [contact for contact in all_contacts if contact.Name == "Contact Region"][0] @@ -76,9 +76,15 @@ ana = ExtAPI.DataModel.Tree.GetObjectsByType(DataModelObjectCategory.Analysis) # Using ACT Automation API -all_contacts2 = ExtAPI.DataModel.Project.Model.Connections.GetChildren[Ansys.ACT.Automation.Mechanical.Connections.ContactRegion](True) -all_remote_points2 = ExtAPI.DataModel.Project.Model.GetChildren[Ansys.ACT.Automation.Mechanical.RemotePoint](True) -all_folders = ExtAPI.DataModel.Project.Model.GetChildren[Ansys.ACT.Automation.Mechanical.TreeGroupingFolder](True) +all_contacts2 = ExtAPI.DataModel.Project.Model.Connections.GetChildren[ + Ansys.ACT.Automation.Mechanical.Connections.ContactRegion +](True) +all_remote_points2 = ExtAPI.DataModel.Project.Model.GetChildren[ + Ansys.ACT.Automation.Mechanical.RemotePoint +](True) +all_folders = ExtAPI.DataModel.Project.Model.GetChildren[ + Ansys.ACT.Automation.Mechanical.TreeGroupingFolder +](True) # %% # Finding Duplicate Objects by Name @@ -92,14 +98,21 @@ duplicates_by_name = [item for item, count in collections.Counter(AllObjNames).items() if count > 1] print(duplicates_by_name) + +# sphinx_gallery_start_ignore +static_struct = Model.AddStaticStructuralAnalysis() +static_struct.Solution.AddEquivalentStress() +# sphinx_gallery_end_ignore + + # %% # Using DataObjects and GetByName # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Example of using DataObjects and GetByName. -c1 = 'Solution' -c2 = 'Far-field Sound Power Level Waterfall Diagram' -c = ExtAPI.DataModel.AnalysisList[0].DataObjects.GetByName(c1).DataObjects.GetByName(c2) +c1 = "Solution" +c2 = "Equivalent Stress" +c = DataModel.AnalysisList[0].DataObjects.GetByName(c1).DataObjects.GetByName(c2) # %% # Using DataObjects, NamesByType, and GetByName @@ -110,17 +123,27 @@ dataobjects = ExtAPI.DataModel.AnalysisList[0].DataObjects for group in dataobjects: print(group.Type) -names = dataobjects.NamesByType('ContactGroup') +names = dataobjects.NamesByType("ContactGroup") for name in names: connet_data_objects = dataobjects.GetByName(name).DataObjects c_names = connet_data_objects.Names for c_name in c_names: type_c = connet_data_objects.GetByName(c_name).Type - if type_c == 'ConnectionGroup': - contacts_list = connet_data_objects.GetByName(c_name).DataObjects.NamesByType('ContactRegion') + if type_c == "ConnectionGroup": + contacts_list = connet_data_objects.GetByName(c_name).DataObjects.NamesByType( + "ContactRegion" + ) for contact in contacts_list: - contact_type = connet_data_objects.GetByName(c_name).DataObjects.GetByName(contact).PropertyValue('ContactType') - contact_state = connet_data_objects.GetByName(c_name).DataObjects.GetByName(contact).PropertyValue("Suppressed") + contact_type = ( + connet_data_objects.GetByName(c_name) + .DataObjects.GetByName(contact) + .PropertyValue("ContactType") + ) + contact_state = ( + connet_data_objects.GetByName(c_name) + .DataObjects.GetByName(contact) + .PropertyValue("Suppressed") + ) if contact_state == 0 and contact_type == 1: new_contact_list.append(contact) print(new_contact_list) @@ -130,16 +153,18 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~ # Example of using GetObjectsByName. -bb = ExtAPI.DataModel.GetObjectsByName("Gray Cast Iron")[0] +bb = ExtAPI.DataModel.GetObjectsByName("Connector\Solid1")[0] # %% # Accessing a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Example of accessing a named selection. -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) -my_nsel = [i for i in NSall if i.Name.startswith("b")][0] -my_nsel2 = [i for i in NSall if i.Name == "aaa"][0] +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) +my_nsel = [i for i in NSall if i.Name.startswith("NSF")][0] +my_nsel2 = [i for i in NSall if i.Name == "NSInsideFaces"][0] # %% # Get All Unsuppressed Bodies and Point Masses @@ -154,8 +179,6 @@ all_pm = [i for i in all_pm if not i.Suppressed] - - # sphinx_gallery_start_ignore # Save the mechdat from pathlib import Path From 0bcdbb632cefa67283f8e958316435360817f324 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 19:12:11 +0000 Subject: [PATCH 14/52] chore: auto fixes from pre-commit hooks --- examples/00_setup/01_setup.py | 29 +++++++++++++-- examples/00_setup/02_geometry.py | 35 +++++++++++++----- examples/00_setup/03_connections.py | 25 ++++++++++++- examples/00_setup/04_named_selections.py | 47 ++++++++++++++++++------ examples/00_setup/05_mesh.py | 22 +++++++++++ examples/00_setup/06_results.py | 39 ++++++++++++++++---- examples/00_setup/07_tree_objects.py | 22 +++++++++++ 7 files changed, 186 insertions(+), 33 deletions(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 4f9e9d493..fdf88f431 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_setup: App @@ -5,6 +27,7 @@ This section has helper scripts for Embedded App """ + # %% # Create an embedded instance and open an existing Mechanical File # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -13,7 +36,7 @@ from ansys.mechanical.core.examples import delete_downloads, download_file mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") -app = App(db_file = mechdat_path, globals=globals()) +app = App(db_file=mechdat_path, globals=globals()) print(app) @@ -27,7 +50,7 @@ geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() -geometry_import_format = (Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic) +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() geometry_import_preferences.ProcessLines = True geometry_import_preferences.NamedSelectionKey = "" @@ -62,4 +85,4 @@ app.close() # Delete the downloaded files delete_downloads() -# sphinx_gallery_end_ignore \ No newline at end of file +# sphinx_gallery_end_ignore diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 02e30dcde..62aeafd32 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_geometry: Geometry @@ -12,6 +34,7 @@ from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file + app = App(globals=globals()) geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() @@ -152,9 +175,7 @@ mylist = [bodyid] selection_manager = ExtAPI.SelectionManager -selection = ExtAPI.SelectionManager.CreateSelectionInfo( - SelectionTypeEnum.GeometryEntities -) +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = mylist selection_manager.NewSelection(selection) @@ -191,9 +212,7 @@ cyl_body_ids.append(body.Id) selection_manager = ExtAPI.SelectionManager -selection = ExtAPI.SelectionManager.CreateSelectionInfo( - SelectionTypeEnum.GeometryEntities -) +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = cyl_body_ids model = ExtAPI.DataModel.Project.Model @@ -205,9 +224,7 @@ # %% # Modify material assignment # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -allbodies = ExtAPI.DataModel.Project.Model.GetChildren( - DataModelObjectCategory.Body, True -) +allbodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) for body in allbodies: body.Material = "Structural Steel" diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index b02ca556e..4f1f8864b 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_connections: Connections @@ -83,6 +105,7 @@ face2 = 160 from pathlib import Path # delete + output_path = Path.cwd() / "out" # delete test_mechdat_path = str(output_path / "temporarycheck.mechdat") # delete app.save_as(test_mechdat_path, overwrite=True) # delete @@ -139,4 +162,4 @@ # %% # TODO : Change Model for Joint and Bearing -# ~~~~~~~~~~~~~~~~ \ No newline at end of file +# ~~~~~~~~~~~~~~~~ diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index 0c0cce210..b965a006d 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_named_selections: Named Selections @@ -6,11 +28,10 @@ This section has helper scripts for Named Selections. """ - - # sphinx_gallery_start_ignore from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file + app = App(globals=globals()) geom_file_path = download_file("example_05_td26_Rubber_Boot_Seal.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() @@ -30,7 +51,6 @@ app.print_tree() - # %% # Fetch all Named Selections # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -41,7 +61,9 @@ # %% # Delete a named selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) # Delete a named selection by name a = [i for i in NSall if i.Name == "Top_Face"][0] @@ -56,7 +78,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ selection_manager = ExtAPI.SelectionManager selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -selection.Ids = [216,221,224] +selection.Ids = [216, 221, 224] model = ExtAPI.DataModel.Project.Model ns2 = model.AddNamedSelection() @@ -92,7 +114,9 @@ # %% # Find a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) # Find a named selection by name a = [i for i in NSall if i.Name == "Rubber_Bodies30"][0] @@ -104,10 +128,12 @@ # %% # Identify Named Selections based on Name and Type # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) # Filter named selections based on keywords in their names -keywords = ["Rubber_Bodies30", "Inner_Faces30","Outer_Faces30"] +keywords = ["Rubber_Bodies30", "Inner_Faces30", "Outer_Faces30"] ns1 = [i for i in NSall if keywords[0] in i.Name] ns2 = [i for i in NSall if keywords[1] in i.Name] ns3 = [i for i in NSall if keywords[2] in i.Name] @@ -115,13 +141,10 @@ # Further filter based on entity type FaceNsels = [ - i - for i in filtered - if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" + i for i in filtered if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" ] - # sphinx_gallery_start_ignore # Save the mechdat from pathlib import Path diff --git a/examples/00_setup/05_mesh.py b/examples/00_setup/05_mesh.py index ca1b0f5ea..3eb037c75 100644 --- a/examples/00_setup/05_mesh.py +++ b/examples/00_setup/05_mesh.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_mesh: Mesh diff --git a/examples/00_setup/06_results.py b/examples/00_setup/06_results.py index b580b4e41..dbcbf05b5 100644 --- a/examples/00_setup/06_results.py +++ b/examples/00_setup/06_results.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_results: Results @@ -6,21 +28,20 @@ This section has helper scripts for Results. """ - # sphinx_gallery_start_ignore import os + from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file mechdat_path = download_file("example_03_simple_bolt_new.mechdat", "pymechanical", "00_basic") -app = App(db_file = mechdat_path, globals=globals()) +app = App(db_file=mechdat_path, globals=globals()) print(app) # sphinx_gallery_end_ignore - # Plot app.plot() @@ -50,7 +71,7 @@ # List Result Objects that can be added # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -all_results = [x for x in dir(static_struct) if str(x)[:3]=="Add"] +all_results = [x for x in dir(static_struct) if str(x)[:3] == "Add"] print(all_results) # %% @@ -116,7 +137,6 @@ print("Number of Result Sets:", result_set_count) - # %% # Export all results in the tree to PNG (2D image) files # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -124,12 +144,15 @@ for result in results: result.Activate() Graphics.Camera.SetSpecificViewOrientation(ViewOrientationType.Front) - image_path = os.path.join(os.getcwd(),"out",result.Name+".png") - Graphics.ExportImage(str(image_path), GraphicsImageExportFormat.PNG, Ansys.Mechanical.Graphics.GraphicsImageExportSettings()) + image_path = os.path.join(os.getcwd(), "out", result.Name + ".png") + Graphics.ExportImage( + str(image_path), + GraphicsImageExportFormat.PNG, + Ansys.Mechanical.Graphics.GraphicsImageExportSettings(), + ) print("Done with Exporting Results") - # sphinx_gallery_start_ignore # Save the mechdat from pathlib import Path diff --git a/examples/00_setup/07_tree_objects.py b/examples/00_setup/07_tree_objects.py index cc92eb3e8..00513779a 100644 --- a/examples/00_setup/07_tree_objects.py +++ b/examples/00_setup/07_tree_objects.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_tree_objects: Tree Objects From f6d18ba8dd888ee9760b496595b377a1eec91ca4 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Thu, 21 Aug 2025 19:13:57 +0000 Subject: [PATCH 15/52] chore: adding changelog file 1287.added.md [dependabot-skip] --- doc/changelog.d/1287.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/1287.added.md diff --git a/doc/changelog.d/1287.added.md b/doc/changelog.d/1287.added.md new file mode 100644 index 000000000..4401a2e6a --- /dev/null +++ b/doc/changelog.d/1287.added.md @@ -0,0 +1 @@ +Update examples with code snippets From 0e02da802018896950f312480e2b205ad00699a3 Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Wed, 10 Sep 2025 01:12:09 +0530 Subject: [PATCH 16/52] loads added --- examples/00_setup/01_setup.py | 29 +-- examples/00_setup/02_geometry.py | 35 +-- examples/00_setup/03_connections.py | 25 +- examples/00_setup/04_named_selections.py | 47 +--- examples/00_setup/05_mesh.py | 22 -- examples/00_setup/06_loads.py | 232 ++++++++++++++++++ .../00_setup/{06_results.py => 07_results.py} | 39 +-- ...{07_tree_objects.py => 08_tree_objects.py} | 22 -- 8 files changed, 265 insertions(+), 186 deletions(-) create mode 100644 examples/00_setup/06_loads.py rename examples/00_setup/{06_results.py => 07_results.py} (68%) rename examples/00_setup/{07_tree_objects.py => 08_tree_objects.py} (84%) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index fdf88f431..4f9e9d493 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -1,25 +1,3 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - """.. _ref_setup: App @@ -27,7 +5,6 @@ This section has helper scripts for Embedded App """ - # %% # Create an embedded instance and open an existing Mechanical File # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -36,7 +13,7 @@ from ansys.mechanical.core.examples import delete_downloads, download_file mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") -app = App(db_file=mechdat_path, globals=globals()) +app = App(db_file = mechdat_path, globals=globals()) print(app) @@ -50,7 +27,7 @@ geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() -geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_format = (Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic) geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() geometry_import_preferences.ProcessLines = True geometry_import_preferences.NamedSelectionKey = "" @@ -85,4 +62,4 @@ app.close() # Delete the downloaded files delete_downloads() -# sphinx_gallery_end_ignore +# sphinx_gallery_end_ignore \ No newline at end of file diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 62aeafd32..02e30dcde 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -1,25 +1,3 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - """.. _ref_geometry: Geometry @@ -34,7 +12,6 @@ from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file - app = App(globals=globals()) geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() @@ -175,7 +152,9 @@ mylist = [bodyid] selection_manager = ExtAPI.SelectionManager -selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection = ExtAPI.SelectionManager.CreateSelectionInfo( + SelectionTypeEnum.GeometryEntities +) selection.Ids = mylist selection_manager.NewSelection(selection) @@ -212,7 +191,9 @@ cyl_body_ids.append(body.Id) selection_manager = ExtAPI.SelectionManager -selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection = ExtAPI.SelectionManager.CreateSelectionInfo( + SelectionTypeEnum.GeometryEntities +) selection.Ids = cyl_body_ids model = ExtAPI.DataModel.Project.Model @@ -224,7 +205,9 @@ # %% # Modify material assignment # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -allbodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) +allbodies = ExtAPI.DataModel.Project.Model.GetChildren( + DataModelObjectCategory.Body, True +) for body in allbodies: body.Material = "Structural Steel" diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index 4f1f8864b..b02ca556e 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -1,25 +1,3 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - """.. _ref_connections: Connections @@ -105,7 +83,6 @@ face2 = 160 from pathlib import Path # delete - output_path = Path.cwd() / "out" # delete test_mechdat_path = str(output_path / "temporarycheck.mechdat") # delete app.save_as(test_mechdat_path, overwrite=True) # delete @@ -162,4 +139,4 @@ # %% # TODO : Change Model for Joint and Bearing -# ~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~ \ No newline at end of file diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index b965a006d..0c0cce210 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -1,25 +1,3 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - """.. _ref_named_selections: Named Selections @@ -28,10 +6,11 @@ This section has helper scripts for Named Selections. """ + + # sphinx_gallery_start_ignore from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file - app = App(globals=globals()) geom_file_path = download_file("example_05_td26_Rubber_Boot_Seal.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() @@ -51,6 +30,7 @@ app.print_tree() + # %% # Fetch all Named Selections # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -61,9 +41,7 @@ # %% # Delete a named selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) # Delete a named selection by name a = [i for i in NSall if i.Name == "Top_Face"][0] @@ -78,7 +56,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ selection_manager = ExtAPI.SelectionManager selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -selection.Ids = [216, 221, 224] +selection.Ids = [216,221,224] model = ExtAPI.DataModel.Project.Model ns2 = model.AddNamedSelection() @@ -114,9 +92,7 @@ # %% # Find a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) # Find a named selection by name a = [i for i in NSall if i.Name == "Rubber_Bodies30"][0] @@ -128,12 +104,10 @@ # %% # Identify Named Selections based on Name and Type # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) # Filter named selections based on keywords in their names -keywords = ["Rubber_Bodies30", "Inner_Faces30", "Outer_Faces30"] +keywords = ["Rubber_Bodies30", "Inner_Faces30","Outer_Faces30"] ns1 = [i for i in NSall if keywords[0] in i.Name] ns2 = [i for i in NSall if keywords[1] in i.Name] ns3 = [i for i in NSall if keywords[2] in i.Name] @@ -141,10 +115,13 @@ # Further filter based on entity type FaceNsels = [ - i for i in filtered if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" + i + for i in filtered + if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" ] + # sphinx_gallery_start_ignore # Save the mechdat from pathlib import Path diff --git a/examples/00_setup/05_mesh.py b/examples/00_setup/05_mesh.py index 3eb037c75..ca1b0f5ea 100644 --- a/examples/00_setup/05_mesh.py +++ b/examples/00_setup/05_mesh.py @@ -1,25 +1,3 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - """.. _ref_mesh: Mesh diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py new file mode 100644 index 000000000..f9a678ffb --- /dev/null +++ b/examples/00_setup/06_loads.py @@ -0,0 +1,232 @@ +""".. _ref_loads: + +Loads and BCs +------------- + +This script contains helper examples for applying loads and boundary conditions in Ansys Mechanical. +""" + +# sphinx_gallery_start_ignore +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file + +app = App(globals=globals()) +geom_file_path = download_file("example_geometry.agdb", "pymechanical", "00_basic") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) +# sphinx_gallery_end_ignore + + +# Plot +app.plot() + +# Print the tree +app.print_tree() + +# %% +# Add an Analysis +# ~~~~~~~~~~~~~~~ +analysis = Model.AddStaticStructuralAnalysis() + +# %% Apply Bolt Pretension by Face ID +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +analysis_settings = Model.Analyses[0].AnalysisSettings +analysis_settings.NumberOfSteps = 6 + +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection.Ids = [312] +csys1 = Model.CoordinateSystems.AddCoordinateSystem() +csys1.OriginLocation = selection + +pretension = Model.Analyses[0].AddBoltPretension() +pretension.Location = selection +pretension.CoordinateSystem = csys1 +pretension.SetDefineBy(1, BoltLoadDefineBy.Load) +pretension.Preload.Output.SetDiscreteValue(0, Quantity("1500[N]")) +for i in range(2, analysis_settings.NumberOfSteps + 1): + pretension.SetDefineBy(int(i), BoltLoadDefineBy.Lock) + +# %% +# Apply a Fixed Support +# ~~~~~~~~~~~~~~~~~~~~~ +support = Model.Analyses[0].AddFixedSupport() +support_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +support_scoping.Ids = [67] +support.Location = support_scoping + +# %% +# Apply a Pressure on the First Face of the First Body +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pressure = Model.Analyses[0].AddPressure() +part1 = Model.Geometry.Children[0] +body1 = part1.Children[0] +face1 = body1.GetGeoBody().Faces[0] # Get the first face of the body. +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection.Entities = [face1] +pressure.Location = selection +pressure.Magnitude.Inputs[0].DiscreteValues = [Quantity("0 [s]"), Quantity("1 [s]")] +pressure.Magnitude.Output.DiscreteValues = [Quantity("10 [Pa]"), Quantity("20 [Pa]")] + +# %% +# Apply a Pressure as a Formula +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pressure = Model.Analyses[0].AddPressure() +pressure_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +pressure_scoping.Ids = [196] +pressure.Location = pressure_scoping +pressure.Magnitude.Output.Formula = "10*time" + +# %% +# Apply a Force +# ~~~~~~~~~~~~~ +force = Model.Analyses[0].AddForce() +force_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +force_scoping.Ids = [31] +force.Location = force_scoping +force.Magnitude.Output.DiscreteValues = [Quantity("11.3 [N]"), Quantity("12.85 [N]")] + +# %% +# Apply Force by Components +# ~~~~~~~~~~~~~~~~~~~~~~~~~ +force = Model.Analyses[0].AddForce() +force_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +force_scoping.Ids = [31] +force.Location = force_scoping +force.DefineBy = LoadDefineBy.Components +force.ZComponent.Output.DiscreteValues = [Quantity("0 [N]"), Quantity("-9 [N]")] + +# %% +# Apply Nodal Forces by Components +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +nodes_list = [66, 89, 105, 315, 470] +force_quantities_list = ["100 [N]", "-200 [N]", "300 [N]", "-400 [N]", "500 [N]"] + +for i in range(len(nodes_list)): + N1 = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.MeshNodes) + N1.Ids = [nodes_list[i]] + ExtAPI.SelectionManager.NewSelection(N1) + + NS = ExtAPI.DataModel.Project.Model.AddNamedSelection() + NS.Name = "Node_" + str(nodes_list[i]) + + Force1 = ExtAPI.DataModel.Project.Model.Analyses[0].AddNodalForce() + Force1.Location = NS + Force1.Name = "NodeAtNode_" + str(nodes_list[i]) + Force1.YComponent.Output.DiscreteValues = [Quantity(force_quantities_list[i])] + Force1.DivideLoadByNodes = False + +# %% +# Apply Force and Fixed Support using Named Selections +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +selection_manager = ExtAPI.SelectionManager +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection.Ids = [312] + +model = ExtAPI.DataModel.Project.Model +ns2 = model.AddNamedSelection() +ns2.Name = "fixed" +ns2.Location = selection +selection_manager.ClearSelection() + +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection.Ids = [312] + +ns2 = model.AddNamedSelection() +ns2.Name = "force" +ns2.Location = selection +selection_manager.ClearSelection() + +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +for_fixed_supp = [i for i in NSall if i.Name.startswith("fixed")][0] +for_force = [i for i in NSall if i.Name.startswith("force")][0] + +f = Model.Analyses[0].AddForce() +f.Location = for_force +f.Name = "Force1" +f.Magnitude.Output.DiscreteValues = [Quantity("10 [N]")] + +fs = model.Analyses[0].AddFixedSupport() +fs.Location = for_fixed_supp +fs.Name = "FixedSupport1" + +# %% +# Apply Radiation - Thermal Analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +radn = Model.Analyses[1].AddRadiation() + +e = radn.Emissivity +e.Output.DiscreteValues = [Quantity("0.36")] + +t = radn.AmbientTemperature +t.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] +t.Output.DiscreteValues = [Quantity("22 [C]"), Quantity("2302 [C]")] + +# %% +# Apply Tabular Pressure for 5 Load Steps +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pressureLoad = ExtAPI.DataModel.Project.Model.Analyses[0].AddPressure() +pressureLoad.Magnitude.Inputs[0].DiscreteValues = [ + Quantity("0 [sec]"), + Quantity("1 [sec]"), + Quantity("2 [sec]"), + Quantity("3 [sec]"), + Quantity("4 [sec]"), + Quantity("5 [sec]"), +] +pressureLoad.Magnitude.Output.DiscreteValues = [ + Quantity("0 [MPa]"), + Quantity("10 [MPa]"), + Quantity("30 [MPa]"), + Quantity("25 [MPa]"), + Quantity("-30 [MPa]"), + Quantity("100 [MPa]"), +] + +# %% +# Applying Direct FE Type Boundary Conditions +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CSall = ExtAPI.DataModel.Project.Model.CoordinateSystems.GetChildren[Ansys.ACT.Automation.Mechanical.CoordinateSystem](True) +a = [i for i in CSall if i.Name == "cyl"][0] +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +n = [i for i in NSall if i.Name == "ns"][0] + +nf = ExtAPI.DataModel.Project.Model.Analyses[0].AddNodalForce() +nf.Location = n +nf.YComponent.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] +nf.IndependentVariable = LoadVariableVariationType.YValue +nf.XYZFunctionCoordinateSystem = a +nf.YComponent.Output.DiscreteValues = [Quantity("0 [N]"), Quantity("100[N]")] + +nd = ExtAPI.DataModel.Project.Model.Analyses[0].AddNodalDisplacement() +nd.Location = n +nd.YComponent.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] +nd.IndependentVariable = LoadVariableVariationType.YValue +nd.XYZFunctionCoordinateSystem = a +nd.YComponent.Output.DiscreteValues = [Quantity("0 [mm]"), Quantity("100[mm]")] + +np = ExtAPI.DataModel.Project.Model.Analyses[0].AddNodalPressure() +np.Location = n +np.Magnitude.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] +np.IndependentVariable = LoadVariableVariationType.YValue +np.XYZFunctionCoordinateSystem = a +np.Magnitude.Output.DiscreteValues = [Quantity("0 [Pa]"), Quantity("100[Pa]")] + +# sphinx_gallery_start_ignore +# Save the mechdat +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test_loads.mechdat") +# app.save_as(test_mechdat_path, overwrite=True) + +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore \ No newline at end of file diff --git a/examples/00_setup/06_results.py b/examples/00_setup/07_results.py similarity index 68% rename from examples/00_setup/06_results.py rename to examples/00_setup/07_results.py index dbcbf05b5..b580b4e41 100644 --- a/examples/00_setup/06_results.py +++ b/examples/00_setup/07_results.py @@ -1,25 +1,3 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - """.. _ref_results: Results @@ -28,20 +6,21 @@ This section has helper scripts for Results. """ + # sphinx_gallery_start_ignore import os - from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file mechdat_path = download_file("example_03_simple_bolt_new.mechdat", "pymechanical", "00_basic") -app = App(db_file=mechdat_path, globals=globals()) +app = App(db_file = mechdat_path, globals=globals()) print(app) # sphinx_gallery_end_ignore + # Plot app.plot() @@ -71,7 +50,7 @@ # List Result Objects that can be added # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -all_results = [x for x in dir(static_struct) if str(x)[:3] == "Add"] +all_results = [x for x in dir(static_struct) if str(x)[:3]=="Add"] print(all_results) # %% @@ -137,6 +116,7 @@ print("Number of Result Sets:", result_set_count) + # %% # Export all results in the tree to PNG (2D image) files # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -144,15 +124,12 @@ for result in results: result.Activate() Graphics.Camera.SetSpecificViewOrientation(ViewOrientationType.Front) - image_path = os.path.join(os.getcwd(), "out", result.Name + ".png") - Graphics.ExportImage( - str(image_path), - GraphicsImageExportFormat.PNG, - Ansys.Mechanical.Graphics.GraphicsImageExportSettings(), - ) + image_path = os.path.join(os.getcwd(),"out",result.Name+".png") + Graphics.ExportImage(str(image_path), GraphicsImageExportFormat.PNG, Ansys.Mechanical.Graphics.GraphicsImageExportSettings()) print("Done with Exporting Results") + # sphinx_gallery_start_ignore # Save the mechdat from pathlib import Path diff --git a/examples/00_setup/07_tree_objects.py b/examples/00_setup/08_tree_objects.py similarity index 84% rename from examples/00_setup/07_tree_objects.py rename to examples/00_setup/08_tree_objects.py index 00513779a..cc92eb3e8 100644 --- a/examples/00_setup/07_tree_objects.py +++ b/examples/00_setup/08_tree_objects.py @@ -1,25 +1,3 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - """.. _ref_tree_objects: Tree Objects From 4bb69913da3412206fa308dab61c7ba54f4421c8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 19:42:29 +0000 Subject: [PATCH 17/52] chore: auto fixes from pre-commit hooks --- examples/00_setup/01_setup.py | 29 +++++++++++++-- examples/00_setup/02_geometry.py | 35 +++++++++++++----- examples/00_setup/03_connections.py | 25 ++++++++++++- examples/00_setup/04_named_selections.py | 47 ++++++++++++++++++------ examples/00_setup/05_mesh.py | 22 +++++++++++ examples/00_setup/06_loads.py | 38 ++++++++++++++++--- examples/00_setup/07_results.py | 39 ++++++++++++++++---- examples/00_setup/08_tree_objects.py | 22 +++++++++++ 8 files changed, 218 insertions(+), 39 deletions(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 4f9e9d493..fdf88f431 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_setup: App @@ -5,6 +27,7 @@ This section has helper scripts for Embedded App """ + # %% # Create an embedded instance and open an existing Mechanical File # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -13,7 +36,7 @@ from ansys.mechanical.core.examples import delete_downloads, download_file mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") -app = App(db_file = mechdat_path, globals=globals()) +app = App(db_file=mechdat_path, globals=globals()) print(app) @@ -27,7 +50,7 @@ geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() -geometry_import_format = (Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic) +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() geometry_import_preferences.ProcessLines = True geometry_import_preferences.NamedSelectionKey = "" @@ -62,4 +85,4 @@ app.close() # Delete the downloaded files delete_downloads() -# sphinx_gallery_end_ignore \ No newline at end of file +# sphinx_gallery_end_ignore diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 02e30dcde..62aeafd32 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_geometry: Geometry @@ -12,6 +34,7 @@ from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file + app = App(globals=globals()) geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() @@ -152,9 +175,7 @@ mylist = [bodyid] selection_manager = ExtAPI.SelectionManager -selection = ExtAPI.SelectionManager.CreateSelectionInfo( - SelectionTypeEnum.GeometryEntities -) +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = mylist selection_manager.NewSelection(selection) @@ -191,9 +212,7 @@ cyl_body_ids.append(body.Id) selection_manager = ExtAPI.SelectionManager -selection = ExtAPI.SelectionManager.CreateSelectionInfo( - SelectionTypeEnum.GeometryEntities -) +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = cyl_body_ids model = ExtAPI.DataModel.Project.Model @@ -205,9 +224,7 @@ # %% # Modify material assignment # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -allbodies = ExtAPI.DataModel.Project.Model.GetChildren( - DataModelObjectCategory.Body, True -) +allbodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) for body in allbodies: body.Material = "Structural Steel" diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index b02ca556e..4f1f8864b 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_connections: Connections @@ -83,6 +105,7 @@ face2 = 160 from pathlib import Path # delete + output_path = Path.cwd() / "out" # delete test_mechdat_path = str(output_path / "temporarycheck.mechdat") # delete app.save_as(test_mechdat_path, overwrite=True) # delete @@ -139,4 +162,4 @@ # %% # TODO : Change Model for Joint and Bearing -# ~~~~~~~~~~~~~~~~ \ No newline at end of file +# ~~~~~~~~~~~~~~~~ diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index 0c0cce210..b965a006d 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_named_selections: Named Selections @@ -6,11 +28,10 @@ This section has helper scripts for Named Selections. """ - - # sphinx_gallery_start_ignore from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file + app = App(globals=globals()) geom_file_path = download_file("example_05_td26_Rubber_Boot_Seal.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() @@ -30,7 +51,6 @@ app.print_tree() - # %% # Fetch all Named Selections # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -41,7 +61,9 @@ # %% # Delete a named selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) # Delete a named selection by name a = [i for i in NSall if i.Name == "Top_Face"][0] @@ -56,7 +78,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ selection_manager = ExtAPI.SelectionManager selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -selection.Ids = [216,221,224] +selection.Ids = [216, 221, 224] model = ExtAPI.DataModel.Project.Model ns2 = model.AddNamedSelection() @@ -92,7 +114,9 @@ # %% # Find a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) # Find a named selection by name a = [i for i in NSall if i.Name == "Rubber_Bodies30"][0] @@ -104,10 +128,12 @@ # %% # Identify Named Selections based on Name and Type # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) # Filter named selections based on keywords in their names -keywords = ["Rubber_Bodies30", "Inner_Faces30","Outer_Faces30"] +keywords = ["Rubber_Bodies30", "Inner_Faces30", "Outer_Faces30"] ns1 = [i for i in NSall if keywords[0] in i.Name] ns2 = [i for i in NSall if keywords[1] in i.Name] ns3 = [i for i in NSall if keywords[2] in i.Name] @@ -115,13 +141,10 @@ # Further filter based on entity type FaceNsels = [ - i - for i in filtered - if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" + i for i in filtered if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" ] - # sphinx_gallery_start_ignore # Save the mechdat from pathlib import Path diff --git a/examples/00_setup/05_mesh.py b/examples/00_setup/05_mesh.py index ca1b0f5ea..3eb037c75 100644 --- a/examples/00_setup/05_mesh.py +++ b/examples/00_setup/05_mesh.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_mesh: Mesh diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index f9a678ffb..a7172b0b0 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_loads: Loads and BCs @@ -52,7 +74,7 @@ for i in range(2, analysis_settings.NumberOfSteps + 1): pretension.SetDefineBy(int(i), BoltLoadDefineBy.Lock) -# %% +# %% # Apply a Fixed Support # ~~~~~~~~~~~~~~~~~~~~~ support = Model.Analyses[0].AddFixedSupport() @@ -91,7 +113,7 @@ force.Location = force_scoping force.Magnitude.Output.DiscreteValues = [Quantity("11.3 [N]"), Quantity("12.85 [N]")] -# %% +# %% # Apply Force by Components # ~~~~~~~~~~~~~~~~~~~~~~~~~ force = Model.Analyses[0].AddForce() @@ -101,7 +123,7 @@ force.DefineBy = LoadDefineBy.Components force.ZComponent.Output.DiscreteValues = [Quantity("0 [N]"), Quantity("-9 [N]")] -# %% +# %% # Apply Nodal Forces by Components # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nodes_list = [66, 89, 105, 315, 470] @@ -191,9 +213,13 @@ # %% # Applying Direct FE Type Boundary Conditions # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -CSall = ExtAPI.DataModel.Project.Model.CoordinateSystems.GetChildren[Ansys.ACT.Automation.Mechanical.CoordinateSystem](True) +CSall = ExtAPI.DataModel.Project.Model.CoordinateSystems.GetChildren[ + Ansys.ACT.Automation.Mechanical.CoordinateSystem +](True) a = [i for i in CSall if i.Name == "cyl"][0] -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ + Ansys.ACT.Automation.Mechanical.NamedSelection +](True) n = [i for i in NSall if i.Name == "ns"][0] nf = ExtAPI.DataModel.Project.Model.Analyses[0].AddNodalForce() @@ -229,4 +255,4 @@ app.close() # Delete the downloaded files delete_downloads() -# sphinx_gallery_end_ignore \ No newline at end of file +# sphinx_gallery_end_ignore diff --git a/examples/00_setup/07_results.py b/examples/00_setup/07_results.py index b580b4e41..dbcbf05b5 100644 --- a/examples/00_setup/07_results.py +++ b/examples/00_setup/07_results.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_results: Results @@ -6,21 +28,20 @@ This section has helper scripts for Results. """ - # sphinx_gallery_start_ignore import os + from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file mechdat_path = download_file("example_03_simple_bolt_new.mechdat", "pymechanical", "00_basic") -app = App(db_file = mechdat_path, globals=globals()) +app = App(db_file=mechdat_path, globals=globals()) print(app) # sphinx_gallery_end_ignore - # Plot app.plot() @@ -50,7 +71,7 @@ # List Result Objects that can be added # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -all_results = [x for x in dir(static_struct) if str(x)[:3]=="Add"] +all_results = [x for x in dir(static_struct) if str(x)[:3] == "Add"] print(all_results) # %% @@ -116,7 +137,6 @@ print("Number of Result Sets:", result_set_count) - # %% # Export all results in the tree to PNG (2D image) files # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -124,12 +144,15 @@ for result in results: result.Activate() Graphics.Camera.SetSpecificViewOrientation(ViewOrientationType.Front) - image_path = os.path.join(os.getcwd(),"out",result.Name+".png") - Graphics.ExportImage(str(image_path), GraphicsImageExportFormat.PNG, Ansys.Mechanical.Graphics.GraphicsImageExportSettings()) + image_path = os.path.join(os.getcwd(), "out", result.Name + ".png") + Graphics.ExportImage( + str(image_path), + GraphicsImageExportFormat.PNG, + Ansys.Mechanical.Graphics.GraphicsImageExportSettings(), + ) print("Done with Exporting Results") - # sphinx_gallery_start_ignore # Save the mechdat from pathlib import Path diff --git a/examples/00_setup/08_tree_objects.py b/examples/00_setup/08_tree_objects.py index cc92eb3e8..00513779a 100644 --- a/examples/00_setup/08_tree_objects.py +++ b/examples/00_setup/08_tree_objects.py @@ -1,3 +1,25 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + """.. _ref_tree_objects: Tree Objects From 6039d76da6c4ae79c3d11be309ed41ad7cae845b Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Wed, 10 Sep 2025 21:21:05 +0530 Subject: [PATCH 18/52] loads ready --- examples/00_setup/06_loads.py | 72 ++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index f9a678ffb..08c761c8e 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -7,11 +7,11 @@ """ # sphinx_gallery_start_ignore + from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file - app = App(globals=globals()) -geom_file_path = download_file("example_geometry.agdb", "pymechanical", "00_basic") +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() @@ -20,8 +20,27 @@ geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) -# sphinx_gallery_end_ignore +Model.Mesh.GenerateMesh() + +selection_manager = ExtAPI.SelectionManager +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection.Ids = [30] +ns2 = Model.AddNamedSelection() +ns2.Name = "fixed" +ns2.Location = selection +selection_manager.ClearSelection() + +selection_manager = ExtAPI.SelectionManager +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection.Ids = [94] + +ns2 = Model.AddNamedSelection() +ns2.Name = "force" +ns2.Location = selection +selection_manager.ClearSelection() + +# sphinx_gallery_end_ignore # Plot app.plot() @@ -40,9 +59,10 @@ analysis_settings.NumberOfSteps = 6 selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -selection.Ids = [312] +selection.Ids = [39] csys1 = Model.CoordinateSystems.AddCoordinateSystem() csys1.OriginLocation = selection +csys1.Name="cyl" pretension = Model.Analyses[0].AddBoltPretension() pretension.Location = selection @@ -57,7 +77,7 @@ # ~~~~~~~~~~~~~~~~~~~~~ support = Model.Analyses[0].AddFixedSupport() support_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -support_scoping.Ids = [67] +support_scoping.Ids = [30] support.Location = support_scoping # %% @@ -78,7 +98,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pressure = Model.Analyses[0].AddPressure() pressure_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -pressure_scoping.Ids = [196] +pressure_scoping.Ids = [95] pressure.Location = pressure_scoping pressure.Magnitude.Output.Formula = "10*time" @@ -87,7 +107,7 @@ # ~~~~~~~~~~~~~ force = Model.Analyses[0].AddForce() force_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -force_scoping.Ids = [31] +force_scoping.Ids = [63] force.Location = force_scoping force.Magnitude.Output.DiscreteValues = [Quantity("11.3 [N]"), Quantity("12.85 [N]")] @@ -96,7 +116,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~ force = Model.Analyses[0].AddForce() force_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -force_scoping.Ids = [31] +force_scoping.Ids = [63] force.Location = force_scoping force.DefineBy = LoadDefineBy.Components force.ZComponent.Output.DiscreteValues = [Quantity("0 [N]"), Quantity("-9 [N]")] @@ -104,18 +124,18 @@ # %% # Apply Nodal Forces by Components # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -nodes_list = [66, 89, 105, 315, 470] -force_quantities_list = ["100 [N]", "-200 [N]", "300 [N]", "-400 [N]", "500 [N]"] +nodes_list = [16,2329] +force_quantities_list = ["100 [N]", "-200 [N]"] for i in range(len(nodes_list)): N1 = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.MeshNodes) N1.Ids = [nodes_list[i]] ExtAPI.SelectionManager.NewSelection(N1) - NS = ExtAPI.DataModel.Project.Model.AddNamedSelection() + NS = Model.AddNamedSelection() NS.Name = "Node_" + str(nodes_list[i]) - Force1 = ExtAPI.DataModel.Project.Model.Analyses[0].AddNodalForce() + Force1 = Model.Analyses[0].AddNodalForce() Force1.Location = NS Force1.Name = "NodeAtNode_" + str(nodes_list[i]) Force1.YComponent.Output.DiscreteValues = [Quantity(force_quantities_list[i])] @@ -126,18 +146,17 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ selection_manager = ExtAPI.SelectionManager selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -selection.Ids = [312] +selection.Ids = [65] -model = ExtAPI.DataModel.Project.Model -ns2 = model.AddNamedSelection() +ns2 = Model.AddNamedSelection() ns2.Name = "fixed" ns2.Location = selection selection_manager.ClearSelection() selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -selection.Ids = [312] +selection.Ids = [65] -ns2 = model.AddNamedSelection() +ns2 = Model.AddNamedSelection() ns2.Name = "force" ns2.Location = selection selection_manager.ClearSelection() @@ -151,14 +170,15 @@ f.Name = "Force1" f.Magnitude.Output.DiscreteValues = [Quantity("10 [N]")] -fs = model.Analyses[0].AddFixedSupport() +fs = Model.Analyses[0].AddFixedSupport() fs.Location = for_fixed_supp fs.Name = "FixedSupport1" # %% # Apply Radiation - Thermal Analysis # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -radn = Model.Analyses[1].AddRadiation() +analysis2 = Model.AddSteadyStateThermalAnalysis() +radn = analysis2.AddRadiation() e = radn.Emissivity e.Output.DiscreteValues = [Quantity("0.36")] @@ -170,7 +190,7 @@ # %% # Apply Tabular Pressure for 5 Load Steps # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -pressureLoad = ExtAPI.DataModel.Project.Model.Analyses[0].AddPressure() +pressureLoad = Model.Analyses[0].AddPressure() pressureLoad.Magnitude.Inputs[0].DiscreteValues = [ Quantity("0 [sec]"), Quantity("1 [sec]"), @@ -191,26 +211,26 @@ # %% # Applying Direct FE Type Boundary Conditions # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -CSall = ExtAPI.DataModel.Project.Model.CoordinateSystems.GetChildren[Ansys.ACT.Automation.Mechanical.CoordinateSystem](True) +CSall = Model.CoordinateSystems.GetChildren[Ansys.ACT.Automation.Mechanical.CoordinateSystem](True) a = [i for i in CSall if i.Name == "cyl"][0] -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) -n = [i for i in NSall if i.Name == "ns"][0] +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +n = [i for i in NSall if i.Name == "force"][0] -nf = ExtAPI.DataModel.Project.Model.Analyses[0].AddNodalForce() +nf = Model.Analyses[0].AddNodalForce() nf.Location = n nf.YComponent.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] nf.IndependentVariable = LoadVariableVariationType.YValue nf.XYZFunctionCoordinateSystem = a nf.YComponent.Output.DiscreteValues = [Quantity("0 [N]"), Quantity("100[N]")] -nd = ExtAPI.DataModel.Project.Model.Analyses[0].AddNodalDisplacement() +nd = Model.Analyses[0].AddNodalDisplacement() nd.Location = n nd.YComponent.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] nd.IndependentVariable = LoadVariableVariationType.YValue nd.XYZFunctionCoordinateSystem = a nd.YComponent.Output.DiscreteValues = [Quantity("0 [mm]"), Quantity("100[mm]")] -np = ExtAPI.DataModel.Project.Model.Analyses[0].AddNodalPressure() +np = Model.Analyses[0].AddNodalPressure() np.Location = n np.Magnitude.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] np.IndependentVariable = LoadVariableVariationType.YValue From 71b7d0ab3f1fd77e07da49e92cc5195c8a8f38ab Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Wed, 10 Sep 2025 21:25:51 +0530 Subject: [PATCH 19/52] loads ready --- examples/00_setup/06_loads.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index c26adbf69..71231adf6 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -233,21 +233,10 @@ # %% # Applying Direct FE Type Boundary Conditions # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -<<<<<<< HEAD CSall = Model.CoordinateSystems.GetChildren[Ansys.ACT.Automation.Mechanical.CoordinateSystem](True) a = [i for i in CSall if i.Name == "cyl"][0] NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) n = [i for i in NSall if i.Name == "force"][0] -======= -CSall = ExtAPI.DataModel.Project.Model.CoordinateSystems.GetChildren[ - Ansys.ACT.Automation.Mechanical.CoordinateSystem -](True) -a = [i for i in CSall if i.Name == "cyl"][0] -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) -n = [i for i in NSall if i.Name == "ns"][0] ->>>>>>> 4bb69913da3412206fa308dab61c7ba54f4421c8 nf = Model.Analyses[0].AddNodalForce() nf.Location = n From d52c496481f49bd4d1dee0c69927fc93263a23f9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Sep 2025 15:56:52 +0000 Subject: [PATCH 20/52] chore: auto fixes from pre-commit hooks --- examples/00_setup/06_loads.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index 71231adf6..da52a73d3 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -32,6 +32,7 @@ from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file + app = App(globals=globals()) geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() @@ -84,7 +85,7 @@ selection.Ids = [39] csys1 = Model.CoordinateSystems.AddCoordinateSystem() csys1.OriginLocation = selection -csys1.Name="cyl" +csys1.Name = "cyl" pretension = Model.Analyses[0].AddBoltPretension() pretension.Location = selection @@ -146,7 +147,7 @@ # %% # Apply Nodal Forces by Components # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -nodes_list = [16,2329] +nodes_list = [16, 2329] force_quantities_list = ["100 [N]", "-200 [N]"] for i in range(len(nodes_list)): From 2ff1e7e9f43454a53244c7256022e4ffde310621 Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Fri, 12 Sep 2025 22:57:42 +0530 Subject: [PATCH 21/52] comments added --- examples/00_setup/01_setup.py | 12 ++++++ examples/00_setup/02_geometry.py | 52 ++++++++++++++++++---- examples/00_setup/03_connections.py | 44 ++++++++++++++----- examples/00_setup/04_named_selections.py | 46 +++++++++++++------- examples/00_setup/05_mesh.py | 34 ++++++++++++--- examples/00_setup/06_loads.py | 26 +++++++++-- examples/00_setup/07_results.py | 40 +++++++++++++---- examples/00_setup/08_tree_objects.py | 55 +++++++++++++++--------- 8 files changed, 235 insertions(+), 74 deletions(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index fdf88f431..9429b4fe1 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -36,10 +36,22 @@ from ansys.mechanical.core.examples import delete_downloads, download_file mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") + +# The following line creates an instance of the app, extracts the global API entry points, +# and merges them into your Python global variables. + app = App(db_file=mechdat_path, globals=globals()) print(app) +# Alternatively, you can use the update_globals method of the App class to update the global variables: +# The second argument, if set to False updates globals without enums like "SelectionTypeEnum" or "LoadDefineBy" +# app = App() +# app.update_globals(globals(), False) + +# For a specific version , use ; +# app = App(version=241) + # %% # Import a Geometry File # ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 62aeafd32..d621b6a65 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -36,51 +36,70 @@ from ansys.mechanical.core.examples import delete_downloads, download_file app = App(globals=globals()) + +# Download the geometry file for the example geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +# Alternatively, you can specify a local file path +# or geom_file_path = r"C:\geometry.agdb" + +# Import the geometry into the Mechanical model geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() + +# Set preferences for geometry import geometry_import_preferences.ProcessLines = True geometry_import_preferences.NamedSelectionKey = "" geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True + +# Perform the geometry import geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) -# Plot +# Plot the imported geometry app.plot() -# Print the tree +# Print the tree structure of the Mechanical model app.print_tree() # %% # Get all bodies # ~~~~~~~~~~~~~~~~~ + +# Retrieve all body objects from the geometry body_objects = Model.Geometry.GetChildren(DataModelObjectCategory.Body, True) -# or +# Alternatively, use the following method: # bodies_objects = Model.Geometry.GetChildren(Ansys.ACT.Automation.Mechanical.Body, True) +# Extract geometric body wrappers for each body object bodies = [body.GetGeoBody() for body in body_objects] # GeoBodyWrapper # or # import itertools # nested_list = [x.Bodies for x in ExtAPI.DataModel.GeoData.Assemblies[0].AllParts] # bodies = list(itertools.chain(*nested_list)) +# Access details of the first body object and its geometric properties bo = body_objects[0] # Access Object Details and RMB options b = bodies[0] # Access Geometric Properties: 'Area', 'GeoData', 'Centroid', 'Faces', etc. # %% # Find Body with Largest Volume # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Set the active unit system to Standard NMM ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM +# Create a list of body names, volumes, and IDs for unsuppressed bodies body_names_volumes = [] for body in body_objects: if body.Suppressed == 0 and body.Volume: body_names_volumes.append((body.Name, body.Volume, body.GetGeoBody().Id)) +# Sort the list and retrieve the body with the largest volume sorted_name_vol = sorted(body_names_volumes) bodyname, volu, bodyid = sorted_name_vol.pop() + +# Print details of the largest body print(f"Unit System is: {ExtAPI.Application.ActiveUnitSystem}") print(f"Name of the Largest Body: '{bodyname}'") print(f"Its Volume: {round(volu.Value, 2)} {volu.Unit}") @@ -89,12 +108,14 @@ # %% # Find Body by its ID # ~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve a body object using its ID b2 = ExtAPI.DataModel.GeoData.GeoEntityById(bodyid) print(f"Body Name: {b2.Name}, Body Id: {b2.Id}") # %% # Find the Part that the body belongs to # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve the name of a body and the part it belongs to using its ID body_name = ExtAPI.DataModel.GeoData.GeoEntityById(59).Name part_name = ExtAPI.DataModel.GeoData.GeoEntityById(59).Part.Name print(f"The Body named '{body_name}' belongs to the part named '{part_name}'") @@ -102,18 +123,24 @@ # %% # Find Body by its ID AND print its Faces, Centroid, etc. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve a body object and its faces, centroids, etc. body2 = ExtAPI.DataModel.GeoData.GeoEntityById(bodyid) +# Get face IDs and centroids for each face face_ids = [face.Id for face in body2.Faces] centroids_of_each_face = [ ExtAPI.DataModel.GeoData.GeoEntityById(face_id).Centroid for face_id in face_ids ] + +# Print face IDs and their centroids for face_id, centroid in zip(face_ids, centroids_of_each_face): print(face_id, list(centroid)) # %% # Get all Vertices # ~~~~~~~~~~~~~~~~~~~ + +# Retrieve all vertex IDs from the geometry vertices = [] geo = ExtAPI.DataModel.GeoData for asm in geo.Assemblies: @@ -126,12 +153,14 @@ # %% # Get all edges of a given length # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all edges with a specified length ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM use_length = 0.100 geo = ExtAPI.DataModel.GeoData edgelist = [] +# Iterate through assemblies, parts, and bodies to find edges of the given length for asm in geo.Assemblies: for part in asm.Parts: for body in part.Bodies: @@ -143,14 +172,16 @@ # %% # Get all circular edges of a given radius # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all circular edges with a specified radius import math -radius = 0.018 -circumference = 2 * math.pi * radius +radius = 0.018 # Target radius +circumference = 2 * math.pi * radius # Calculate circumference geo = ExtAPI.DataModel.GeoData circlelist = [] +# Iterate through assemblies, parts, and bodies to find circular edges for asm in geo.Assemblies: for part in asm.Parts: for body in part.Bodies: @@ -165,6 +196,7 @@ # %% # Get Radius of a selected edge # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve the radius of a specific edge if it is circular my_edge = ExtAPI.DataModel.GeoData.GeoEntityById(27) my_edge_radius = my_edge.Radius if str(my_edge.CurveType) == "GeoCurveCircle" else 0.0 print(my_edge_radius) @@ -172,6 +204,7 @@ # %% # Create a Named Selection from a list of body Ids # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a named selection for a list of body IDs mylist = [bodyid] selection_manager = ExtAPI.SelectionManager @@ -186,6 +219,7 @@ # %% # Find a Named Selection with a prefix # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve a named selection whose name starts with a specific prefix NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) @@ -195,6 +229,7 @@ # %% # Create a Named Selection of all bodies with a cylindrical face # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + geo = ExtAPI.DataModel.GeoData cyl_body_ids = [] @@ -224,6 +259,7 @@ # %% # Modify material assignment # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Assign a specific material to all bodies in the model allbodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) for body in allbodies: body.Material = "Structural Steel" @@ -231,11 +267,12 @@ # %% # Get all Coordinate Systems # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all coordinate systems in the model tree_CS = ExtAPI.DataModel.Project.Model.CoordinateSystems # sphinx_gallery_start_ignore -# Save the mechdat +# Save the Mechanical database file from pathlib import Path output_path = Path.cwd() / "out" @@ -243,8 +280,7 @@ # app.save_as(test_mechdat_path, overwrite=True) -# Close the app +# Close the application and delete downloaded files app.close() -# Delete the downloaded files delete_downloads() # sphinx_gallery_end_ignore diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index 4f1f8864b..f795160c4 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -33,28 +33,40 @@ from ansys.mechanical.core.examples import delete_downloads, download_file app = App(globals=globals()) + +# Download the geometry file for the example geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") + +# Import the geometry into the Mechanical model geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() + +# Set preferences for geometry import geometry_import_preferences.ProcessLines = True geometry_import_preferences.NamedSelectionKey = "" geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True + +# Perform the geometry import geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) # sphinx_gallery_end_ignore +# Plot the imported geometry app.plot() -# Print the tree +# Print the tree structure of the Mechanical model app.print_tree() # %% # Get information about all Contacts Defined # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all contact regions defined in the model all_contacts = ExtAPI.DataModel.Project.Model.Connections.GetChildren( DataModelObjectCategory.ContactRegion, True ) + +# Print details of each contact region for contact in all_contacts: print( f"\n{contact.Parent.Name} > {contact.Name} : {contact.ContactType} : {contact.Suppressed} : {contact.ContactFormulation}" @@ -66,6 +78,8 @@ # %% # Create Automatic Connections on a chosen named selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a new connection group for automatic connections + contactgroup = ExtAPI.DataModel.Project.Model.Connections.AddConnectionGroup() contactgroup.FaceFace = True contactgroup.FaceEdge = contactgroup.FaceEdge.No @@ -73,22 +87,28 @@ contactgroup.Priority = contactgroup.Priority.FaceOverEdge contactgroup.InternalObject.DetectCylindricalFacesType = 1 +# Retrieve a named selection for the connection group NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) my_nsel = [i for i in NSall if i.Name == "bodies_5"][0] +# Assign the named selection to the connection group and create automatic connections contactgroup.Location = my_nsel contactgroup.CreateAutomaticConnections() +# Refresh the tree structure to reflect the changes mytree = ExtAPI.DataModel.Tree mytree.Refresh() # %% # Create a Contact region using face named selections # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Add a new contact region to the model c = ExtAPI.DataModel.Project.Model.Connections c1 = c.AddContactRegion() + +# Retrieve named selections for the source and target locations NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) @@ -101,19 +121,22 @@ # %% # Insert a Joint using face IDs # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Define face IDs for the joint face1 = 135 face2 = 160 + from pathlib import Path # delete output_path = Path.cwd() / "out" # delete test_mechdat_path = str(output_path / "temporarycheck.mechdat") # delete app.save_as(test_mechdat_path, overwrite=True) # delete - +# Add a new joint to the model model = ExtAPI.DataModel.Project.Model j = model.Connections.AddJoint() +# Define the reference and mobile locations for the joint using face IDs reference_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) reference_scoping.Ids = [face1] j.ReferenceLocation = reference_scoping @@ -125,18 +148,25 @@ # %% # Define a Bearing # ~~~~~~~~~~~~~~~~ +# Add a new bearing connection to the model brg = ExtAPI.DataModel.Project.Model.Connections.AddBearing() + +# Set the reference rotation plane for the bearing brg.ReferenceRotationPlane = RotationPlane.XY + +# Define stiffness values for the bearing brg.StiffnessK11.Output.DiscreteValues = [Quantity("11 [N/m]")] brg.StiffnessK22.Output.DiscreteValues = [Quantity("22 [N/m]")] brg.StiffnessK21.Output.DiscreteValues = [Quantity("21 [N/m]")] brg.StiffnessK12.Output.DiscreteValues = [Quantity("12 [N/m]")] +# Define damping values for the bearing brg.DampingC11.Output.DiscreteValues = [Quantity("111 [N sec m^-1]")] brg.DampingC22.Output.DiscreteValues = [Quantity("122 [N sec m^-1]")] brg.DampingC12.Output.DiscreteValues = [Quantity("112 [N sec m^-1]")] brg.DampingC21.Output.DiscreteValues = [Quantity("121 [N sec m^-1]")] +# Retrieve named selections for the reference and mobile locations NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) @@ -145,7 +175,7 @@ # sphinx_gallery_start_ignore -# Save the mechdat +# Save the Mechanical database file from pathlib import Path output_path = Path.cwd() / "out" @@ -153,13 +183,7 @@ # app.save_as(test_mechdat_path, overwrite=True) -# Close the app +# Close the application and delete downloaded files app.close() -# Delete the downloaded files delete_downloads() # sphinx_gallery_end_ignore - - -# %% -# TODO : Change Model for Joint and Bearing -# ~~~~~~~~~~~~~~~~ diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index b965a006d..bf99bb802 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -33,66 +33,78 @@ from ansys.mechanical.core.examples import delete_downloads, download_file app = App(globals=globals()) +# Download the geometry file for the example geom_file_path = download_file("example_05_td26_Rubber_Boot_Seal.agdb", "pymechanical", "00_basic") + +# Import the geometry into the Mechanical model geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() + +# Set preferences for geometry import geometry_import_preferences.ProcessLines = True geometry_import_preferences.NamedSelectionKey = "" geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True + +# Perform the geometry import geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) # sphinx_gallery_end_ignore -# Plot +# Plot the imported geometry app.plot() -# Print the tree +# Print the tree structure of the Mechanical model app.print_tree() # %% # Fetch all Named Selections -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# ALL NAMED SELECTIONS +# Retrieve all named selections in the model nsall = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.NamedSelections.NamedSelection) # %% # Delete a named selection -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all named selections in the project NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) -# Delete a named selection by name +# Delete a named selection by its name a = [i for i in NSall if i.Name == "Top_Face"][0] a.Delete() -# Alternative way to delete by name +# Alternative way to delete a named selection by name b = ExtAPI.DataModel.GetObjectsByName("Bottom_Face")[0] b.Delete() # %% # Create a named selection -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a new named selection for specific geometry entities selection_manager = ExtAPI.SelectionManager selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = [216, 221, 224] +# Add the named selection to the model model = ExtAPI.DataModel.Project.Model ns2 = model.AddNamedSelection() -ns2.Name = "faces" +ns2.Name = "faces" # Set the name of the named selection ns2.Location = selection -selection_manager.ClearSelection() +selection_manager.ClearSelection() # Clear the selection after creation - delete # %% # Create a Named Selection by Worksheet -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a named selection using worksheet criteria NS1 = DataModel.Project.Model.AddNamedSelection() NS1.ScopingMethod = GeometryDefineByType.Worksheet GenerationCriteria = NS1.GenerationCriteria +# Add criteria to the worksheet for selecting entities Criterion1 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() Criterion1.Action = SelectionActionType.Add Criterion1.EntityType = SelectionType.GeoFace @@ -109,16 +121,18 @@ Criterion2.Value = Quantity("0 [m]") GenerationCriteria.Add(Criterion2) +# Generate the named selection based on the criteria NS1.Generate() # %% # Find a Named Selection -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all named selections in the project NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) -# Find a named selection by name +# Find a specific named selection by its name a = [i for i in NSall if i.Name == "Rubber_Bodies30"][0] # Access entities in the named selection @@ -128,6 +142,7 @@ # %% # Identify Named Selections based on Name and Type # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all named selections in the project NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) @@ -139,7 +154,7 @@ ns3 = [i for i in NSall if keywords[2] in i.Name] filtered = ns1 + ns2 + ns3 -# Further filter based on entity type +# Further filter the named selections based on entity type FaceNsels = [ i for i in filtered if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" ] @@ -154,8 +169,7 @@ app.save_as(test_mechdat_path, overwrite=True) -# Close the app +# Close the application and delete downloaded files app.close() -# Delete the downloaded files delete_downloads() # sphinx_gallery_end_ignore diff --git a/examples/00_setup/05_mesh.py b/examples/00_setup/05_mesh.py index 3eb037c75..f97a7e53a 100644 --- a/examples/00_setup/05_mesh.py +++ b/examples/00_setup/05_mesh.py @@ -33,32 +33,39 @@ from ansys.mechanical.core.examples import delete_downloads, download_file app = App(globals=globals()) + +# Download and import the geometry file geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() + +# Define geometry import format and preferences geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() geometry_import_preferences.ProcessLines = True geometry_import_preferences.NamedSelectionKey = "" geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True + +# Import the geometry into the project geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) # sphinx_gallery_end_ignore -# Plot +# Plot the imported geometry app.plot() -# Print the tree +# Print the Mechanical tree structure app.print_tree() # %% # Insert a Local Meshing Control for a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +# Get all named selections and pick the one named "shank" NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) use_nsel = [i for i in NSall if i.Name == "shank"][0] +# Add an Automatic Method mesh control scoped to the named selection ms = Model.Mesh.AddAutomaticMethod() ms.Location = use_nsel ms.Method = ms.Method.AllTriAllTet @@ -68,6 +75,7 @@ # %% # Generate Mesh # ~~~~~~~~~~~~~ +# Generate the mesh and print mesh object state Model.Mesh.GenerateMesh() print(Model.Mesh.ObjectState) @@ -75,15 +83,21 @@ # %% # Get Element Count of a meshed body # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Access mesh data meshdata = DataModel.MeshDataByName("Global") print(use_nsel.Ids[0]) + +# Retrieve body entity from geometry geoBody = DataModel.GeoData.GeoEntityById(use_nsel.Ids[0]) body = Model.Geometry.GetBody(geoBody) + +# Get mesh region corresponding to that body and print element count meshregion = meshdata.MeshRegionById(geoBody.Id) print(body.Name, meshregion.ElementCount) # sphinx_gallery_start_ignore +# Clear the generated mesh to start fresh for next operations Model.Mesh.ClearGeneratedData() # sphinx_gallery_end_ignore @@ -91,9 +105,11 @@ # %% # Insert a Sweep Method (Scoping Method: Named Selection) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Get all named selections and pick the one named "bodies_5" NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) use_nsel = [i for i in NSall if i.Name == "bodies_5"][0] +# Add a sweep meshing method scoped to the named selection mesh = Model.Mesh mesh_method = mesh.AddAutomaticMethod() mesh_method.Location = use_nsel @@ -102,14 +118,19 @@ # %% # Insert a Mesh Sizing Control (Scoping Method: Geometry Selection) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Get all named selections and pick the one containing "bottom_surface" NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) ns = [i for i in NSall if "bottom_surface" in i.Name][0] +# Extract bottom face and its edges bot_face = DataModel.GeoData.GeoEntityById(ns.Ids[0]) body_ids = [edge.Id for edge in bot_face.Edges] + +# Create a geometry selection object from edges sel = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) sel.Ids = body_ids +# Apply mesh sizing control to the selection mesh = Model.Mesh mesh_sizing = mesh.AddSizing() mesh_sizing.Location = sel @@ -117,7 +138,8 @@ # sphinx_gallery_start_ignore -# Save the mechdat +# Save the project as a .mechdat file (currently commented out) + from pathlib import Path output_path = Path.cwd() / "out" @@ -125,8 +147,8 @@ # app.save_as(test_mechdat_path, overwrite=True) -# Close the app +# Close the Mechanical application app.close() -# Delete the downloaded files +# Delete any downloaded example files delete_downloads() # sphinx_gallery_end_ignore diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index 71231adf6..5b9ac3431 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -42,8 +42,11 @@ geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + +# Generate mesh for the imported geometry Model.Mesh.GenerateMesh() +# Create named selections for fixed support and force application selection_manager = ExtAPI.SelectionManager selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = [30] @@ -73,6 +76,7 @@ # %% # Add an Analysis # ~~~~~~~~~~~~~~~ +# Create a static structural analysis analysis = Model.AddStaticStructuralAnalysis() # %% Apply Bolt Pretension by Face ID @@ -80,23 +84,28 @@ analysis_settings = Model.Analyses[0].AnalysisSettings analysis_settings.NumberOfSteps = 6 +# Define coordinate system at face ID = 39 selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = [39] csys1 = Model.CoordinateSystems.AddCoordinateSystem() csys1.OriginLocation = selection csys1.Name="cyl" +# Apply bolt pretension load pretension = Model.Analyses[0].AddBoltPretension() pretension.Location = selection pretension.CoordinateSystem = csys1 pretension.SetDefineBy(1, BoltLoadDefineBy.Load) pretension.Preload.Output.SetDiscreteValue(0, Quantity("1500[N]")) +# Lock the bolt for remaining steps for i in range(2, analysis_settings.NumberOfSteps + 1): pretension.SetDefineBy(int(i), BoltLoadDefineBy.Lock) # %% # Apply a Fixed Support # ~~~~~~~~~~~~~~~~~~~~~ +# Define a fixed support boundary condition on a specific geometry entity. + support = Model.Analyses[0].AddFixedSupport() support_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) support_scoping.Ids = [30] @@ -108,7 +117,7 @@ pressure = Model.Analyses[0].AddPressure() part1 = Model.Geometry.Children[0] body1 = part1.Children[0] -face1 = body1.GetGeoBody().Faces[0] # Get the first face of the body. +face1 = body1.GetGeoBody().Faces[0] # First face of first body selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Entities = [face1] pressure.Location = selection @@ -149,6 +158,7 @@ nodes_list = [16,2329] force_quantities_list = ["100 [N]", "-200 [N]"] +# Loop through nodes and apply nodal force for i in range(len(nodes_list)): N1 = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.MeshNodes) N1.Ids = [nodes_list[i]] @@ -166,6 +176,7 @@ # %% # Apply Force and Fixed Support using Named Selections # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create named selections for force and fixed support selection_manager = ExtAPI.SelectionManager selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = [65] @@ -183,10 +194,12 @@ ns2.Location = selection selection_manager.ClearSelection() +# Retrieve named selections NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) for_fixed_supp = [i for i in NSall if i.Name.startswith("fixed")][0] for_force = [i for i in NSall if i.Name.startswith("force")][0] +# Apply load and support via named selections f = Model.Analyses[0].AddForce() f.Location = for_force f.Name = "Force1" @@ -233,11 +246,13 @@ # %% # Applying Direct FE Type Boundary Conditions # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve coordinate system named "cyl" and named selection "force" CSall = Model.CoordinateSystems.GetChildren[Ansys.ACT.Automation.Mechanical.CoordinateSystem](True) a = [i for i in CSall if i.Name == "cyl"][0] NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) n = [i for i in NSall if i.Name == "force"][0] +# Nodal Force nf = Model.Analyses[0].AddNodalForce() nf.Location = n nf.YComponent.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] @@ -245,6 +260,7 @@ nf.XYZFunctionCoordinateSystem = a nf.YComponent.Output.DiscreteValues = [Quantity("0 [N]"), Quantity("100[N]")] +# Nodal Displacement nd = Model.Analyses[0].AddNodalDisplacement() nd.Location = n nd.YComponent.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] @@ -252,6 +268,7 @@ nd.XYZFunctionCoordinateSystem = a nd.YComponent.Output.DiscreteValues = [Quantity("0 [mm]"), Quantity("100[mm]")] +# Nodal Pressure np = Model.Analyses[0].AddNodalPressure() np.Location = n np.Magnitude.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] @@ -260,15 +277,16 @@ np.Magnitude.Output.DiscreteValues = [Quantity("0 [Pa]"), Quantity("100[Pa]")] # sphinx_gallery_start_ignore -# Save the mechdat +# Save the project as a mechdat file (currently commented out) + from pathlib import Path output_path = Path.cwd() / "out" test_mechdat_path = str(output_path / "test_loads.mechdat") # app.save_as(test_mechdat_path, overwrite=True) -# Close the app +# Close Mechanical application app.close() -# Delete the downloaded files +# Delete downloaded files delete_downloads() # sphinx_gallery_end_ignore diff --git a/examples/00_setup/07_results.py b/examples/00_setup/07_results.py index dbcbf05b5..fe1c2f7c6 100644 --- a/examples/00_setup/07_results.py +++ b/examples/00_setup/07_results.py @@ -31,10 +31,14 @@ # sphinx_gallery_start_ignore import os +# Import Mechanical API core and example utilities from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file +# Download an example Mechanical database (.mechdat file) mechdat_path = download_file("example_03_simple_bolt_new.mechdat", "pymechanical", "00_basic") + +# Launch Mechanical and open the example database app = App(db_file=mechdat_path, globals=globals()) print(app) @@ -42,19 +46,23 @@ # sphinx_gallery_end_ignore -# Plot +# Plot the geometry of the model app.plot() -# Print the tree +# Print the Mechanical tree structure app.print_tree() # %% # Solve # ~~~~~ +# Access the first analysis system (Static Structural) static_struct = app.DataModel.AnalysisList[0] + +# Clear any previously generated solution data static_struct.Solution.ClearGeneratedData() print("Solution Status:", static_struct.Solution.Status) +# Run the solver static_struct.Solution.Solve() print("Solution Status:", static_struct.Solution.Status) @@ -62,7 +70,7 @@ # %% # Results that are accessible for GetResult # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +# List names of results already available in the solution result_names = static_struct.GetResultsData().ResultNames print("Available Results:", ", ".join(result_names)) @@ -70,7 +78,7 @@ # %% # List Result Objects that can be added # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +# Show all available result objects that can be inserted into the solution all_results = [x for x in dir(static_struct) if str(x)[:3] == "Add"] print(all_results) @@ -78,13 +86,14 @@ # Insert a Result # ~~~~~~~~~~~~~~~ - +# Add a Total Deformation result and evaluate it total_deformation = static_struct.Solution.AddTotalDeformation() total_deformation.EvaluateAllResults() # %% Access max and min of a result # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve the minimum and maximum values for total deformation minimum_deformation = total_deformation.Minimum maximum_deformation = total_deformation.Maximum print(f"Minimum Deformation: {minimum_deformation}") @@ -93,6 +102,7 @@ # %% # Get Results by Node Number # ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Extract displacement ("U") results for a specific node ID node_number = 2000 result_data = static_struct.GetResultsData() node_values = result_data.GetResult("U").GetNodeValues(node_number) @@ -103,35 +113,45 @@ # ~~~~~~~~~~~~~~~~~~~~ -# Insert a command object +# Insert a command snippet into the solution (for custom APDL/commands) cs = static_struct.Solution.AddCommandSnippet() # %% # Fatigue Results # ~~~~~~~~~~~~~~~ +# Add a Fatigue Tool to the solution + solution = static_struct.Solution fatigue_tool = solution.AddFatigueTool() +# Insert a Safety Factor calculation under the fatigue tool safety_factor = fatigue_tool.AddSafetyFactor() + +# Scope safety factor evaluation to specific mesh nodes selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.MeshNodes) selection.Ids = [1, 2] safety_factor.Location = selection + +# Get the minimum safety factor value minimum = safety_factor.Minimum print("Safety Factor Minimum:", minimum) -# Export safety factor to a text file +# Export safety factor results to a text file fname = "safety_factor_results.txt" safety_factor.ExportToTextFile(True, fname) # %% # User-defined Result # ~~~~~~~~~~~~~~~~~~~ +# Insert a User-Defined Result object user_result = static_struct.Solution.AddUserDefinedResult() print("User-defined Result Added:", user_result) # %% # Get number of result sets # ~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve the number of available result sets (time/frequency steps) + reader = static_struct.GetResultsData() result_set_count = reader.ListTimeFreq.Count print("Number of Result Sets:", result_set_count) @@ -140,6 +160,7 @@ # %% # Export all results in the tree to PNG (2D image) files # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Iterate over all result objects and export each one to an image results = DataModel.GetObjectsByType(DataModelObjectCategory.Result) for result in results: result.Activate() @@ -154,7 +175,7 @@ # sphinx_gallery_start_ignore -# Save the mechdat +# Save the project as a .mechdat file from pathlib import Path output_path = Path.cwd() / "out" @@ -162,7 +183,8 @@ # app.save_as(test_mechdat_path, overwrite=True) -# Close the app +# Close Mechanical application + app.close() # Delete the downloaded files # delete_downloads() diff --git a/examples/00_setup/08_tree_objects.py b/examples/00_setup/08_tree_objects.py index 00513779a..9f190478d 100644 --- a/examples/00_setup/08_tree_objects.py +++ b/examples/00_setup/08_tree_objects.py @@ -32,37 +32,44 @@ from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file +# Initialize the Mechanical application app = App(globals=globals()) + +# Download and import the geometry file geom_file_path = download_file("Valve.pmdb", "pymechanical", "embedding") geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic + +# Define geometry import format and preferences geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() geometry_import_preferences.ProcessLines = True geometry_import_preferences.NamedSelectionKey = "" geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True + +# Import the geometry into the project geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) # sphinx_gallery_end_ignore -# Plot +# Plot the imported geometry app.plot() -# Print the tree +# Print the Mechanical tree structure app.print_tree() # %% # Accessing Geometry # ~~~~~~~~~~~~~~~~~~ -# Example of accessing geometry by ID. +# Access a specific geometry entity by its ID. body = ExtAPI.DataModel.GeoData.GeoEntityById(312) # %% # Accessing Mesh Data # ~~~~~~~~~~~~~~~~~~~~~~ -# Example of accessing mesh data by name. +# Access specific mesh data by name and ID. node = ExtAPI.DataModel.MeshDataByName("Global").NodeById(555) element = ExtAPI.DataModel.MeshDataByName("Global").ElementById(444) @@ -72,32 +79,32 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Examples of accessing all objects, bodies, named selections, and contact regions. -# All tree objects +# Retrieve all objects in the tree AllObj = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.DataModelObject, True) -# All bodies +# Retrieve all bodies all_bodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) -# All named selections +# Retrieve all named selections ns_all = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.NamedSelections.NamedSelection) -# All contact regions +# Retrieve all contact regions abc = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.ContactRegion) all_contacts = ExtAPI.DataModel.Project.Model.Connections.GetChildren( DataModelObjectCategory.ContactRegion, True ) -# A specific contact region +# Access a specific contact region by name my_contact = [contact for contact in all_contacts if contact.Name == "Contact Region"][0] -# All result objects of a specific type +# Retrieve all result objects of a specific type (e.g., Normal Stress) all_norm_stress = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.Result.NormalStress) -# Other examples +# Retrieve other objects such as remote points and analyses all_remote_points = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.RemotePoint) ana = ExtAPI.DataModel.Tree.GetObjectsByType(DataModelObjectCategory.Analysis) -# Using ACT Automation API +# Using the ACT Automation API to retrieve specific objects all_contacts2 = ExtAPI.DataModel.Project.Model.Connections.GetChildren[ Ansys.ACT.Automation.Mechanical.Connections.ContactRegion ](True) @@ -111,17 +118,21 @@ # %% # Finding Duplicate Objects by Name # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Example of finding duplicate objects by name. +# Identify duplicate objects in the project tree based on their names. import collections +# Retrieve all objects and their names AllObj = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.DataModelObject, True) AllObjNames = [x.Name for x in AllObj] + +# Find duplicate names duplicates_by_name = [item for item, count in collections.Counter(AllObjNames).items() if count > 1] print(duplicates_by_name) # sphinx_gallery_start_ignore +# Add a static structural analysis and equivalent stress result for testing static_struct = Model.AddStaticStructuralAnalysis() static_struct.Solution.AddEquivalentStress() # sphinx_gallery_end_ignore @@ -130,8 +141,8 @@ # %% # Using DataObjects and GetByName # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Example of using DataObjects and GetByName. +# Access specific data objects by their names. c1 = "Solution" c2 = "Equivalent Stress" c = DataModel.AnalysisList[0].DataObjects.GetByName(c1).DataObjects.GetByName(c2) @@ -139,12 +150,14 @@ # %% # Using DataObjects, NamesByType, and GetByName # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Example of using DataObjects, NamesByType, and GetByName. +# Access and filter contact regions based on their properties. new_contact_list = [] dataobjects = ExtAPI.DataModel.AnalysisList[0].DataObjects for group in dataobjects: print(group.Type) + +# Retrieve names of all contact groups names = dataobjects.NamesByType("ContactGroup") for name in names: connet_data_objects = dataobjects.GetByName(name).DataObjects @@ -173,14 +186,13 @@ # %% # Using GetObjectsByName # ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Example of using GetObjectsByName. - +# Access a specific object by its name. bb = ExtAPI.DataModel.GetObjectsByName("Connector\Solid1")[0] # %% # Accessing a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Example of accessing a named selection. +# Access specific named selections by their names. NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection @@ -193,16 +205,18 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Example of getting all unsuppressed bodies and point masses. +# Retrieve all unsuppressed bodies all_bodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) all_bodies = [i for i in all_bodies if not i.Suppressed] print(len(all_bodies)) +# Retrieve all unsuppressed point masses all_pm = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.PointMass, True) all_pm = [i for i in all_pm if not i.Suppressed] # sphinx_gallery_start_ignore -# Save the mechdat +# Save the Mechanical database file from pathlib import Path output_path = Path.cwd() / "out" @@ -210,8 +224,7 @@ # app.save_as(test_mechdat_path, overwrite=True) -# Close the app +# Close the application and delete downloaded files app.close() -# Delete the downloaded files delete_downloads() # sphinx_gallery_end_ignore From 55058e881984f2b0fa057995e4343847b332dc1b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 12 Sep 2025 17:31:19 +0000 Subject: [PATCH 22/52] chore: auto fixes from pre-commit hooks --- examples/00_setup/02_geometry.py | 2 +- examples/00_setup/04_named_selections.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index d621b6a65..8e5983455 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -86,7 +86,7 @@ # %% # Find Body with Largest Volume # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Set the active unit system to Standard NMM +# Set the active unit system to Standard NMM ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM # Create a list of body names, volumes, and IDs for unsuppressed bodies diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index bf99bb802..433d915aa 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -92,9 +92,9 @@ # Add the named selection to the model model = ExtAPI.DataModel.Project.Model ns2 = model.AddNamedSelection() -ns2.Name = "faces" # Set the name of the named selection +ns2.Name = "faces" # Set the name of the named selection ns2.Location = selection -selection_manager.ClearSelection() # Clear the selection after creation - delete +selection_manager.ClearSelection() # Clear the selection after creation - delete # %% # Create a Named Selection by Worksheet From 90b73d44255f7c4fb90cd87ce5122d139a5511c1 Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Fri, 12 Sep 2025 23:26:43 +0530 Subject: [PATCH 23/52] all htmls generated --- examples/00_setup/08_tree_objects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/00_setup/08_tree_objects.py b/examples/00_setup/08_tree_objects.py index 9f190478d..0fdf4bf69 100644 --- a/examples/00_setup/08_tree_objects.py +++ b/examples/00_setup/08_tree_objects.py @@ -226,5 +226,5 @@ # Close the application and delete downloaded files app.close() -delete_downloads() +# delete_downloads() # sphinx_gallery_end_ignore From dc5068afff3bd9030d8456abaf182396d42311ab Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Fri, 12 Sep 2025 13:32:39 -0500 Subject: [PATCH 24/52] fix style --- examples/00_setup/01_setup.py | 5 +++-- examples/00_setup/03_connections.py | 3 ++- examples/00_setup/06_loads.py | 24 ++++++++++++------------ examples/00_setup/07_results.py | 2 +- examples/00_setup/08_tree_objects.py | 2 +- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 9429b4fe1..1866d5c7f 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -44,8 +44,9 @@ print(app) -# Alternatively, you can use the update_globals method of the App class to update the global variables: -# The second argument, if set to False updates globals without enums like "SelectionTypeEnum" or "LoadDefineBy" +# Alternatively, you can use the update_globals method of the App class to +# update the global variables.The second argument, if set to False updates +# globals without enums like "SelectionTypeEnum" or "LoadDefineBy" # app = App() # app.update_globals(globals(), False) diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index f795160c4..179c5e105 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -69,7 +69,8 @@ # Print details of each contact region for contact in all_contacts: print( - f"\n{contact.Parent.Name} > {contact.Name} : {contact.ContactType} : {contact.Suppressed} : {contact.ContactFormulation}" + f"\n{contact.Parent.Name} > {contact.Name} : {contact.ContactType} : " + f"{contact.Suppressed} : {contact.ContactFormulation}" ) print("Contact: ", contact.ContactBodies, list(contact.SourceLocation.Ids)) print("Target: ", contact.TargetBodies, list(contact.TargetLocation.Ids)) diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index d4fe2b15b..9425394a9 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -262,20 +262,20 @@ nf.YComponent.Output.DiscreteValues = [Quantity("0 [N]"), Quantity("100[N]")] # Nodal Displacement -nd = Model.Analyses[0].AddNodalDisplacement() -nd.Location = n -nd.YComponent.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] -nd.IndependentVariable = LoadVariableVariationType.YValue -nd.XYZFunctionCoordinateSystem = a -nd.YComponent.Output.DiscreteValues = [Quantity("0 [mm]"), Quantity("100[mm]")] +nodal_displacement = Model.Analyses[0].AddNodalDisplacement() +nodal_displacement.Location = n +nodal_displacement.YComponent.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] +nodal_displacement.IndependentVariable = LoadVariableVariationType.YValue +nodal_displacement.XYZFunctionCoordinateSystem = a +nodal_displacement.YComponent.Output.DiscreteValues = [Quantity("0 [mm]"), Quantity("100[mm]")] # Nodal Pressure -np = Model.Analyses[0].AddNodalPressure() -np.Location = n -np.Magnitude.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] -np.IndependentVariable = LoadVariableVariationType.YValue -np.XYZFunctionCoordinateSystem = a -np.Magnitude.Output.DiscreteValues = [Quantity("0 [Pa]"), Quantity("100[Pa]")] +nodal_pressure = Model.Analyses[0].AddNodalPressure() +nodal_pressure.Location = n +nodal_pressure.Magnitude.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] +nodal_pressure.IndependentVariable = LoadVariableVariationType.YValue +nodal_pressure.XYZFunctionCoordinateSystem = a +nodal_pressure.Magnitude.Output.DiscreteValues = [Quantity("0 [Pa]"), Quantity("100[Pa]")] # sphinx_gallery_start_ignore # Save the project as a mechdat file (currently commented out) diff --git a/examples/00_setup/07_results.py b/examples/00_setup/07_results.py index fe1c2f7c6..0bd5a699e 100644 --- a/examples/00_setup/07_results.py +++ b/examples/00_setup/07_results.py @@ -187,5 +187,5 @@ app.close() # Delete the downloaded files -# delete_downloads() +delete_downloads() # sphinx_gallery_end_ignore diff --git a/examples/00_setup/08_tree_objects.py b/examples/00_setup/08_tree_objects.py index 0fdf4bf69..9f190478d 100644 --- a/examples/00_setup/08_tree_objects.py +++ b/examples/00_setup/08_tree_objects.py @@ -226,5 +226,5 @@ # Close the application and delete downloaded files app.close() -# delete_downloads() +delete_downloads() # sphinx_gallery_end_ignore From 85234e45937afd89cb86b0c0855fa3e259afd2b3 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Fri, 12 Sep 2025 16:58:44 -0500 Subject: [PATCH 25/52] fix crash --- examples/00_setup/07_results.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/00_setup/07_results.py b/examples/00_setup/07_results.py index 0bd5a699e..02dbb13d7 100644 --- a/examples/00_setup/07_results.py +++ b/examples/00_setup/07_results.py @@ -138,7 +138,7 @@ # Export safety factor results to a text file fname = "safety_factor_results.txt" -safety_factor.ExportToTextFile(True, fname) +safety_factor.ExportToTextFile(fname) # %% # User-defined Result @@ -155,7 +155,7 @@ reader = static_struct.GetResultsData() result_set_count = reader.ListTimeFreq.Count print("Number of Result Sets:", result_set_count) - +reader.Dispose() # %% # Export all results in the tree to PNG (2D image) files From cb19e16814ef8c19a53f3a925c893794fc5c0df7 Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Sun, 14 Sep 2025 23:05:11 +0530 Subject: [PATCH 26/52] dispose added --- examples/00_setup/07_results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/00_setup/07_results.py b/examples/00_setup/07_results.py index fe1c2f7c6..1e19b91be 100644 --- a/examples/00_setup/07_results.py +++ b/examples/00_setup/07_results.py @@ -155,7 +155,7 @@ reader = static_struct.GetResultsData() result_set_count = reader.ListTimeFreq.Count print("Number of Result Sets:", result_set_count) - +reader.Dispose() # %% # Export all results in the tree to PNG (2D image) files From 20a8e6a9fb8a85d6428c659c6442b21bc7d29a73 Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Thu, 18 Sep 2025 10:24:04 +0530 Subject: [PATCH 27/52] geom description --- examples/00_setup/02_geometry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 8e5983455..33545926b 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -25,7 +25,7 @@ Geometry -------- -This section has helper scripts for Geometry +This section contains utility scripts for working with Geometry, including importing, analyzing, and accessing geometric data, as well as utilizing it for downstream preprocessing operations in Mechanical simulations. """ # %% From 26a0af66facda6ea7cbff1a4a7ae8ac247bf8862 Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Thu, 18 Sep 2025 22:00:07 +0530 Subject: [PATCH 28/52] added more snippets from prompt forge --- examples/00_setup/01_setup.py | 14 +++ examples/00_setup/02_geometry.py | 68 ++++++++--- examples/00_setup/03_connections.py | 47 +++++-- examples/00_setup/04_named_selections.py | 39 ++++-- examples/00_setup/05_mesh.py | 15 ++- examples/00_setup/06_loads.py | 148 +++++++++++++++++++++++ examples/00_setup/08_tree_objects.py | 58 +++++---- 7 files changed, 325 insertions(+), 64 deletions(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 1866d5c7f..11290cd30 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -71,6 +71,20 @@ geometry_import_preferences.ProcessMaterialProperties = True geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) +# %% +# Set Units +# ~~~~~~~~~~~~~~~~~~~~~~~ + +app.ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM +app.ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian +app.ExtAPI.Application.ActiveAngularVelocityUnit=AngularVelocityUnitType.RadianPerSecond + +# %% +# View messages in Mechanical using PyMechanical +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +app.messages.show() + # %% # Plot and Print the Tree (To check model so far) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 33545926b..12aa36f7d 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -25,7 +25,7 @@ Geometry -------- -This section contains utility scripts for working with Geometry, including importing, analyzing, and accessing geometric data, as well as utilizing it for downstream preprocessing operations in Mechanical simulations. +This section contains utility scripts for working with Geometry, including importing, analyzing, and accessing geometric data, as well as utilizing it for downstream preprocessing operations in Mechanical simulations. Coordinate Systems too are covered here. """ # %% @@ -109,27 +109,27 @@ # Find Body by its ID # ~~~~~~~~~~~~~~~~~~~~~~ # Retrieve a body object using its ID -b2 = ExtAPI.DataModel.GeoData.GeoEntityById(bodyid) +b2 = DataModel.GeoData.GeoEntityById(bodyid) print(f"Body Name: {b2.Name}, Body Id: {b2.Id}") # %% # Find the Part that the body belongs to # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve the name of a body and the part it belongs to using its ID -body_name = ExtAPI.DataModel.GeoData.GeoEntityById(59).Name -part_name = ExtAPI.DataModel.GeoData.GeoEntityById(59).Part.Name +body_name = DataModel.GeoData.GeoEntityById(59).Name +part_name = DataModel.GeoData.GeoEntityById(59).Part.Name print(f"The Body named '{body_name}' belongs to the part named '{part_name}'") # %% # Find Body by its ID AND print its Faces, Centroid, etc. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve a body object and its faces, centroids, etc. -body2 = ExtAPI.DataModel.GeoData.GeoEntityById(bodyid) +body2 = DataModel.GeoData.GeoEntityById(bodyid) # Get face IDs and centroids for each face face_ids = [face.Id for face in body2.Faces] centroids_of_each_face = [ - ExtAPI.DataModel.GeoData.GeoEntityById(face_id).Centroid for face_id in face_ids + DataModel.GeoData.GeoEntityById(face_id).Centroid for face_id in face_ids ] # Print face IDs and their centroids @@ -142,7 +142,7 @@ # Retrieve all vertex IDs from the geometry vertices = [] -geo = ExtAPI.DataModel.GeoData +geo = DataModel.GeoData for asm in geo.Assemblies: for part in asm.Parts: for body in part.Bodies: @@ -157,7 +157,7 @@ ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM use_length = 0.100 -geo = ExtAPI.DataModel.GeoData +geo = DataModel.GeoData edgelist = [] # Iterate through assemblies, parts, and bodies to find edges of the given length @@ -178,7 +178,7 @@ radius = 0.018 # Target radius circumference = 2 * math.pi * radius # Calculate circumference -geo = ExtAPI.DataModel.GeoData +geo = DataModel.GeoData circlelist = [] # Iterate through assemblies, parts, and bodies to find circular edges @@ -197,7 +197,7 @@ # Get Radius of a selected edge # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve the radius of a specific edge if it is circular -my_edge = ExtAPI.DataModel.GeoData.GeoEntityById(27) +my_edge = DataModel.GeoData.GeoEntityById(27) my_edge_radius = my_edge.Radius if str(my_edge.CurveType) == "GeoCurveCircle" else 0.0 print(my_edge_radius) @@ -212,7 +212,7 @@ selection.Ids = mylist selection_manager.NewSelection(selection) -ns2 = ExtAPI.DataModel.Project.Model.AddNamedSelection() +ns2 = Model.AddNamedSelection() ns2.Name = "bodies2" ns2.Location = selection @@ -220,7 +220,7 @@ # Find a Named Selection with a prefix # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve a named selection whose name starts with a specific prefix -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ +NSall = Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) my_nsel = [i for i in NSall if i.Name.startswith("b")][0] @@ -230,7 +230,7 @@ # Create a Named Selection of all bodies with a cylindrical face # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -geo = ExtAPI.DataModel.GeoData +geo = DataModel.GeoData cyl_body_ids = [] for asm in geo.Assemblies: @@ -250,8 +250,7 @@ selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = cyl_body_ids -model = ExtAPI.DataModel.Project.Model -ns2 = model.AddNamedSelection() +ns2 = Model.AddNamedSelection() ns2.Name = "bodies_with_cyl_face" ns2.Location = selection selection_manager.ClearSelection() @@ -260,15 +259,48 @@ # Modify material assignment # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Assign a specific material to all bodies in the model -allbodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) +allbodies = Model.GetChildren(DataModelObjectCategory.Body, True) for body in allbodies: body.Material = "Structural Steel" # %% # Get all Coordinate Systems -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all coordinate systems in the model -tree_CS = ExtAPI.DataModel.Project.Model.CoordinateSystems +tree_CS = Model.CoordinateSystems + +# %% +# Add a cylindrical coordinate system +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a new coordinate system +csys = Model.CoordinateSystems.AddCoordinateSystem() +# place csys origin at arbitrary (0,25,50) location +csys.SetOriginLocation(Quantity(0,"in"), Quantity(25,"in"), Quantity(50,"in")) +# set primary X axis to arbitrary (1,2,3) direction +csys.PrimaryAxisDirection = Vector3D(1,2,3) + +# %% +# Add a cartesian coordinate system at a location (0,25,50) inches with primary X axis towards an arbitrary (1,2,3) direction +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a new coordinate system +csys = Model.CoordinateSystems.AddCoordinateSystem() +# place csys origin at arbitrary (0,25,50) location +csys.SetOriginLocation(Quantity(0,"in"), Quantity(25,"in"), Quantity(50,"in")) +# set primary X axis to arbitrary (1,2,3) direction +csys.PrimaryAxisDirection = Vector3D(1,2,3) + + + +# %% +# Find a coordinate system by name +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a new coordinate system +csys = app.Model.CoordinateSystems.AddCoordinateSystem() +# place csys origin at arbitrary (0,25,50) location +csys.SetOriginLocation(Quantity(0,"in"), Quantity(25,"in"), Quantity(50,"in")) +# set primary X axis to arbitrary (1,2,3) direction +csys.PrimaryAxisDirection = Vector3D(1,2,3) + # sphinx_gallery_start_ignore diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index 179c5e105..1b2cf3f9c 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -62,10 +62,14 @@ # Get information about all Contacts Defined # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all contact regions defined in the model -all_contacts = ExtAPI.DataModel.Project.Model.Connections.GetChildren( +all_contacts = Model.Connections.GetChildren( DataModelObjectCategory.ContactRegion, True ) +# Print count of all contact regions +numContacts = all_contacts.Count +print("There are %s contact regions" % (numContacts) ) + # Print details of each contact region for contact in all_contacts: print( @@ -76,12 +80,13 @@ print("Target: ", contact.TargetBodies, list(contact.TargetLocation.Ids)) + # %% # Create Automatic Connections on a chosen named selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Create a new connection group for automatic connections -contactgroup = ExtAPI.DataModel.Project.Model.Connections.AddConnectionGroup() +contactgroup = Model.Connections.AddConnectionGroup() contactgroup.FaceFace = True contactgroup.FaceEdge = contactgroup.FaceEdge.No contactgroup.GroupBy = contactgroup.GroupBy.Faces @@ -89,7 +94,7 @@ contactgroup.InternalObject.DetectCylindricalFacesType = 1 # Retrieve a named selection for the connection group -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ +NSall = Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) my_nsel = [i for i in NSall if i.Name == "bodies_5"][0] @@ -99,18 +104,17 @@ contactgroup.CreateAutomaticConnections() # Refresh the tree structure to reflect the changes -mytree = ExtAPI.DataModel.Tree -mytree.Refresh() +DataModel.Tree.Refresh() # %% # Create a Contact region using face named selections # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Add a new contact region to the model -c = ExtAPI.DataModel.Project.Model.Connections +c = DataModel.Project.Model.Connections c1 = c.AddContactRegion() # Retrieve named selections for the source and target locations -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ +NSall = Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) a = [i for i in NSall if i.Name == "block1_washer_cont"][0] @@ -119,6 +123,17 @@ c1.SourceLocation = a +# %% +# Insert a fixed body to ground joint +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +connections = Model.Connections +fixed_joint = connections.AddJoint() +fixed_joint.ConnectionType=JointScopingType.BodyToGround +fixed_joint.Type = JointType.Fixed +fixed_joint.MobileLocation = app.DataModel.GetObjectsByName("block1_washer_cont")[0] + + + # %% # Insert a Joint using face IDs # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -134,8 +149,7 @@ app.save_as(test_mechdat_path, overwrite=True) # delete # Add a new joint to the model -model = ExtAPI.DataModel.Project.Model -j = model.Connections.AddJoint() +j = Model.Connections.AddJoint() # Define the reference and mobile locations for the joint using face IDs reference_scoping = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) @@ -146,11 +160,22 @@ mobile_scoping.Ids = [face2] j.MobileLocation = mobile_scoping +# %% +# Define a ground to body spring with 1 N/m stiffness scoped to preexisting named selection +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +connections = Model.Connections +spring = connections.AddSpring() +spring.ConnectionType=JointScopingType.BodyToGround +spring.LongitudinalStiffness = Quantity(1, "N m^-1") +spring.MobileScopingMethod = GeometryDefineByType.Component +spring.MobileScopeLocation = app.DataModel.GetObjectsByName("block1_washer_cont")[0] + + # %% # Define a Bearing # ~~~~~~~~~~~~~~~~ # Add a new bearing connection to the model -brg = ExtAPI.DataModel.Project.Model.Connections.AddBearing() +brg = Model.Connections.AddBearing() # Set the reference rotation plane for the bearing brg.ReferenceRotationPlane = RotationPlane.XY @@ -168,7 +193,7 @@ brg.DampingC21.Output.DiscreteValues = [Quantity("121 [N sec m^-1]")] # Retrieve named selections for the reference and mobile locations -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ +NSall = Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) brg.ReferenceLocation = [i for i in NSall if i.Name == "shank_surface"][0] diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index 433d915aa..46f8084bb 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -63,13 +63,13 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all named selections in the model -nsall = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.NamedSelections.NamedSelection) +nsall = DataModel.GetObjectsByType(DataModelObjectCategory.NamedSelections.NamedSelection) # %% # Delete a named selection # ~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all named selections in the project -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ +NSall = Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) @@ -78,7 +78,7 @@ a.Delete() # Alternative way to delete a named selection by name -b = ExtAPI.DataModel.GetObjectsByName("Bottom_Face")[0] +b = DataModel.GetObjectsByName("Bottom_Face")[0] b.Delete() # %% @@ -90,8 +90,7 @@ selection.Ids = [216, 221, 224] # Add the named selection to the model -model = ExtAPI.DataModel.Project.Model -ns2 = model.AddNamedSelection() +ns2 = Model.AddNamedSelection() ns2.Name = "faces" # Set the name of the named selection ns2.Location = selection selection_manager.ClearSelection() # Clear the selection after creation - delete @@ -100,10 +99,13 @@ # Create a Named Selection by Worksheet # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Create a named selection using worksheet criteria -NS1 = DataModel.Project.Model.AddNamedSelection() +NS1 = Model.AddNamedSelection() NS1.ScopingMethod = GeometryDefineByType.Worksheet GenerationCriteria = NS1.GenerationCriteria +# Let us create a named selection "faces_for_support" +# using worksheet for all faces at y=0 or z=0 m + # Add criteria to the worksheet for selecting entities Criterion1 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() Criterion1.Action = SelectionActionType.Add @@ -122,13 +124,32 @@ GenerationCriteria.Add(Criterion2) # Generate the named selection based on the criteria +NS1.Name="faces_for_support" NS1.Generate() + + +# %% +# Extract all the details of a named selection worksheet named "faces_for_support" +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NSall=app.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +my_nsel = [i for i in NSall if i.Name == "shaft"][0] +worksheet = my_nsel.GenerationCriteria +for i in range(0,len(list(worksheet))): + print(worksheet[i].Action) + print(worksheet[i].EntityType) + print(worksheet[i].Criterion) + print(worksheet[i].Operator) + print(worksheet[i].Value) + print(worksheet[i].CoordinateSystem.Name) + + + # %% # Find a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all named selections in the project -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ +NSall = Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) @@ -143,7 +164,7 @@ # Identify Named Selections based on Name and Type # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all named selections in the project -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ +NSall = Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) @@ -156,7 +177,7 @@ # Further filter the named selections based on entity type FaceNsels = [ - i for i in filtered if str(ExtAPI.DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" + i for i in filtered if str(DataModel.GeoData.GeoEntityById(i.Ids[0]).Type) == "GeoFace" ] diff --git a/examples/00_setup/05_mesh.py b/examples/00_setup/05_mesh.py index f97a7e53a..c4b251d7d 100644 --- a/examples/00_setup/05_mesh.py +++ b/examples/00_setup/05_mesh.py @@ -57,6 +57,14 @@ # Print the Mechanical tree structure app.print_tree() +# %% +# Set Global Mesh Settings +# ~~~~~~~~~~~~~~~~~~~~~~~~ +mesh=Model.Mesh +mesh.ElementSize = Quantity('37 [mm]') +mesh.ElementOrder = ElementOrder.Linear + + # %% # Insert a Local Meshing Control for a Named Selection @@ -95,11 +103,10 @@ meshregion = meshdata.MeshRegionById(geoBody.Id) print(body.Name, meshregion.ElementCount) - -# sphinx_gallery_start_ignore -# Clear the generated mesh to start fresh for next operations +# %% +# Clear generated mesh +# ~~~~~~~~~~~~~~~~~~~~~~~~ Model.Mesh.ClearGeneratedData() -# sphinx_gallery_end_ignore # %% diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index 9425394a9..69498e590 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -153,6 +153,18 @@ force.DefineBy = LoadDefineBy.Components force.ZComponent.Output.DiscreteValues = [Quantity("0 [N]"), Quantity("-9 [N]")] +# %% +# Add a remote displacement with 6 degrees of freedom fixed +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +remote_disp = analysis.AddRemoteDisplacement() +remote_disp.XComponent.Output.DiscreteValues = [Quantity("0 [mm]")] +remote_disp.YComponent.Output.DiscreteValues = [Quantity("0 [mm]")] +remote_disp.ZComponent.Output.DiscreteValues = [Quantity("0 [mm]")] +remote_disp.RotationX.Output.DiscreteValues = [Quantity("0 [deg]")] +remote_disp.RotationY.Output.DiscreteValues = [Quantity("0 [deg]")] +remote_disp.RotationZ.Output.DiscreteValues = [Quantity("0 [deg]")] + + # %% # Apply Nodal Forces by Components # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -223,6 +235,37 @@ t.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]")] t.Output.DiscreteValues = [Quantity("22 [C]"), Quantity("2302 [C]")] +# %% +# Add a temperature load applied to a named selection +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +temp_bc = analysis2.AddTemperature() +temp_bc.Location = app.DataModel.GetObjectsByName("fixed")[0] +temp_bc.Magnitude.Output.DiscreteValues = [Quantity("22[C]"), Quantity("60[C]")] +temp_bc.Magnitude.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]"), Quantity("2 [sec]")] +temp_bc.Magnitude.Output.DiscreteValues = [Quantity("22[C]"), Quantity("50[C]"), Quantity("80[C]")] + + +# %% +# # %% +# Create a convection load +# ~~~~~~~~~~~~~~~~~~~~~~~~ +# analysis = app.Model.AddSteadyStateThermalAnalysis() +try: + named_sel = app.Model.NamedSelections.Children[0] +except: + print("Named Selection not found") + +convection = Model.Analyses[0].AddConvection() +if named_sel != None: + convection.Location = named_sel + +convection.AmbientTemperature.Inputs[0].DiscreteValues = [Quantity("0 [s]"), Quantity("1 [s]")] # Set the time values +convection.AmbientTemperature.Output.DiscreteValues = [Quantity('760 [C]'), Quantity('800 [C]')] # Set the Ambient Temperature values +convection.FilmCoefficient.Inputs[0].DiscreteValues = [Quantity("0 [s]"), Quantity("1 [s]")] # Set the time values +convection.FilmCoefficient.Output.DiscreteValues = [Quantity("100 [W m^-1 m^-1 K^-1]"), Quantity("150 [W m^-1 m^-1 K^-1]")] #Set the HTC values + + + # %% # Apply Tabular Pressure for 5 Load Steps # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -277,6 +320,111 @@ nodal_pressure.XYZFunctionCoordinateSystem = a nodal_pressure.Magnitude.Output.DiscreteValues = [Quantity("0 [Pa]"), Quantity("100[Pa]")] + +# %% +# Set Automatic Time Stepping setting for a specific Load Step +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +analysis_settings = Model.Analyses[0].AnalysisSettings +analysis_settings.CurrentStepNumber = 1 +print(analysis_settings.AutomaticTimeStepping ) + + +# %% +# Set Step end time +# ~~~~~~~~~~~~~~~~~ +analysis_settings.CurrentStepNumber = 5 +analysis_settings.StepEndTime = Quantity('0.1 [sec]') + +# %% +# Define Load steps with end times +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +analysis_settings.NumberOfSteps=3 + +analysis_settings.CurrentStepNumber = 1 +analysis_settings.StepEndTime = Quantity('1.0 [sec]') + +analysis_settings.CurrentStepNumber = 2 +analysis_settings.StepEndTime = Quantity('10.0 [sec]') + +analysis_settings.CurrentStepNumber = 3 +analysis_settings.StepEndTime = Quantity('100.0 [sec]') + + +# %% +# Define substep sizing using times +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +analysis_settings.CurrentStepNumber = 1 +analysis_settings.StepEndTime = Quantity('0.1 [sec]') +analysis_settings.AutomaticTimeStepping =analysis_settings.AutomaticTimeStepping.On +analysis_settings.DefineBy=analysis_settings.DefineBy.Time +analysis_settings.InitialTimeStep = Quantity("0.005 [s]") +analysis_settings.MaximumTimeStep = Quantity("0.5 [s]") +analysis_settings.MinimumTimeStep = Quantity("0.0005 [s]") + + +# %% +# Define substep sizing using steps +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +analysis_settings.CurrentStepNumber = 1 +analysis_settings.StepEndTime = Quantity('0.1 [sec]') +analysis_settings.AutomaticTimeStepping =analysis_settings.AutomaticTimeStepping.On +analysis_settings.DefineBy=analysis_settings.DefineBy.Substeps +analysis_settings.InitialSubsteps=15 +analysis_settings.MinimumSubsteps=5 +analysis_settings.MaximumSubsteps=50 + +# %% +# Set Iterative solver type for solution +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +analysis_settings.SolverType = SolverType.Iterative + +# other options from dir(SolverType) : +# analysis_settings.SolverType = SolverType.Direct +# analysis_settings.SolverType = SolverType.FullDamped +# analysis_settings.SolverType=SolverType.ProgramControlled +# analysis_settings.SolverType=SolverType.ReducedDamped +# analysis_settings.SolverType=SolverType.Subspace +# analysis_settings.SolverType=SolverType.Supernode +# analysis_settings.SolverType=SolverType.Unsymmetric + + +# %% +# Change the solver unit system +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +analysis_settings.SolverUnits = SolverUnitsControlType.Manual +analysis_settings.SolverUnitSystem = WBUnitSystemType.ConsistentMKS + +# %% +# Get path to the Solver files directory +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +solve_dir = analysis_settings.ScratchSolverFilesDirectory +print(solve_dir) + +# To get path to the scratch Solver files directory for an unsaved file +# solve_dir = analysis_settings.SolverFilesDirectory + + +# %% +# Solve an analysis +# ~~~~~~~~~~~~~~~~~ +Model.Analyses[0].Solution.Activate() +Model.Analyses[0].Solution.Solve(True) + + +# %% +# Set the step end time and time steps in Transient structural analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# analysis = app.Model.AddTransientStructuralAnalysis() +analysis_settings=analysis.AnalysisSettings +analysis_settings.SetStepEndTime( 1, Quantity("0.4 [s]")) +analysis_settings.SetInitialTimeStep(1,Quantity("0.0001 [s]")) +analysis_settings.SetMinimumTimeStep(1,Quantity("0.0000001 [s]")) +analysis_settings.SetMaximumTimeStep(1,Quantity("0.01 [s]")) + + + + + # sphinx_gallery_start_ignore # Save the project as a mechdat file (currently commented out) diff --git a/examples/00_setup/08_tree_objects.py b/examples/00_setup/08_tree_objects.py index 9f190478d..b53ed2a48 100644 --- a/examples/00_setup/08_tree_objects.py +++ b/examples/00_setup/08_tree_objects.py @@ -64,15 +64,28 @@ # ~~~~~~~~~~~~~~~~~~ # Access a specific geometry entity by its ID. -body = ExtAPI.DataModel.GeoData.GeoEntityById(312) +body = DataModel.GeoData.GeoEntityById(312) + +# %% +# Print all visible properties of a tree +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +tree_object= DataModel.GetObjectsByName("Contact Region")[0] +for prop in tree_object.Properties: + print(f'{prop.Name}: {prop.InternalValue}') +# or +for tree_object in tree_object.VisibleProperties: + print(tree_object.Caption + " | " + tree_object.StringValue) + + + # %% # Accessing Mesh Data -# ~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~ # Access specific mesh data by name and ID. -node = ExtAPI.DataModel.MeshDataByName("Global").NodeById(555) -element = ExtAPI.DataModel.MeshDataByName("Global").ElementById(444) +node = DataModel.MeshDataByName("Global").NodeById(555) +element = DataModel.MeshDataByName("Global").ElementById(444) # %% # Accessing All Objects and Child Objects @@ -80,17 +93,17 @@ # Examples of accessing all objects, bodies, named selections, and contact regions. # Retrieve all objects in the tree -AllObj = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.DataModelObject, True) +AllObj = Model.GetChildren(DataModelObjectCategory.DataModelObject, True) # Retrieve all bodies -all_bodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) +all_bodies = Model.GetChildren(DataModelObjectCategory.Body, True) # Retrieve all named selections -ns_all = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.NamedSelections.NamedSelection) +ns_all = DataModel.GetObjectsByType(DataModelObjectCategory.NamedSelections.NamedSelection) # Retrieve all contact regions -abc = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.ContactRegion) -all_contacts = ExtAPI.DataModel.Project.Model.Connections.GetChildren( +abc = DataModel.GetObjectsByType(DataModelObjectCategory.ContactRegion) +all_contacts = Model.Connections.GetChildren( DataModelObjectCategory.ContactRegion, True ) @@ -98,20 +111,20 @@ my_contact = [contact for contact in all_contacts if contact.Name == "Contact Region"][0] # Retrieve all result objects of a specific type (e.g., Normal Stress) -all_norm_stress = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.Result.NormalStress) +all_norm_stress = DataModel.GetObjectsByType(DataModelObjectCategory.Result.NormalStress) # Retrieve other objects such as remote points and analyses -all_remote_points = ExtAPI.DataModel.GetObjectsByType(DataModelObjectCategory.RemotePoint) -ana = ExtAPI.DataModel.Tree.GetObjectsByType(DataModelObjectCategory.Analysis) +all_remote_points = DataModel.GetObjectsByType(DataModelObjectCategory.RemotePoint) +ana = DataModel.Tree.GetObjectsByType(DataModelObjectCategory.Analysis) # Using the ACT Automation API to retrieve specific objects -all_contacts2 = ExtAPI.DataModel.Project.Model.Connections.GetChildren[ +all_contacts2 = Model.Connections.GetChildren[ Ansys.ACT.Automation.Mechanical.Connections.ContactRegion ](True) -all_remote_points2 = ExtAPI.DataModel.Project.Model.GetChildren[ +all_remote_points2 = Model.GetChildren[ Ansys.ACT.Automation.Mechanical.RemotePoint ](True) -all_folders = ExtAPI.DataModel.Project.Model.GetChildren[ +all_folders = Model.GetChildren[ Ansys.ACT.Automation.Mechanical.TreeGroupingFolder ](True) @@ -123,7 +136,7 @@ import collections # Retrieve all objects and their names -AllObj = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.DataModelObject, True) +AllObj = Model.GetChildren(DataModelObjectCategory.DataModelObject, True) AllObjNames = [x.Name for x in AllObj] # Find duplicate names @@ -153,7 +166,7 @@ # Access and filter contact regions based on their properties. new_contact_list = [] -dataobjects = ExtAPI.DataModel.AnalysisList[0].DataObjects +dataobjects = DataModel.AnalysisList[0].DataObjects for group in dataobjects: print(group.Type) @@ -187,14 +200,14 @@ # Using GetObjectsByName # ~~~~~~~~~~~~~~~~~~~~~~~~~ # Access a specific object by its name. -bb = ExtAPI.DataModel.GetObjectsByName("Connector\Solid1")[0] +bb = DataModel.GetObjectsByName("Connector\Solid1")[0] # %% # Accessing a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Access specific named selections by their names. -NSall = ExtAPI.DataModel.Project.Model.NamedSelections.GetChildren[ +NSall = Model.NamedSelections.GetChildren[ Ansys.ACT.Automation.Mechanical.NamedSelection ](True) my_nsel = [i for i in NSall if i.Name.startswith("NSF")][0] @@ -202,19 +215,20 @@ # %% # Get All Unsuppressed Bodies and Point Masses -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Example of getting all unsuppressed bodies and point masses. # Retrieve all unsuppressed bodies -all_bodies = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.Body, True) +all_bodies = Model.GetChildren(DataModelObjectCategory.Body, True) all_bodies = [i for i in all_bodies if not i.Suppressed] print(len(all_bodies)) # Retrieve all unsuppressed point masses -all_pm = ExtAPI.DataModel.Project.Model.GetChildren(DataModelObjectCategory.PointMass, True) +all_pm = Model.GetChildren(DataModelObjectCategory.PointMass, True) all_pm = [i for i in all_pm if not i.Suppressed] + # sphinx_gallery_start_ignore # Save the Mechanical database file from pathlib import Path From 8aacf8ab962a5255ace7487b5710c04c4ca8c86b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Sep 2025 16:30:41 +0000 Subject: [PATCH 29/52] chore: auto fixes from pre-commit hooks --- examples/00_setup/01_setup.py | 2 +- examples/00_setup/02_geometry.py | 22 +++----- examples/00_setup/03_connections.py | 24 +++----- examples/00_setup/04_named_selections.py | 20 ++----- examples/00_setup/05_mesh.py | 5 +- examples/00_setup/06_loads.py | 70 ++++++++++++++---------- examples/00_setup/08_tree_objects.py | 23 ++------ 7 files changed, 71 insertions(+), 95 deletions(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 11290cd30..d77ecda1e 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -77,7 +77,7 @@ app.ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM app.ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian -app.ExtAPI.Application.ActiveAngularVelocityUnit=AngularVelocityUnitType.RadianPerSecond +app.ExtAPI.Application.ActiveAngularVelocityUnit = AngularVelocityUnitType.RadianPerSecond # %% # View messages in Mechanical using PyMechanical diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 12aa36f7d..b0b13affe 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -128,9 +128,7 @@ # Get face IDs and centroids for each face face_ids = [face.Id for face in body2.Faces] -centroids_of_each_face = [ - DataModel.GeoData.GeoEntityById(face_id).Centroid for face_id in face_ids -] +centroids_of_each_face = [DataModel.GeoData.GeoEntityById(face_id).Centroid for face_id in face_ids] # Print face IDs and their centroids for face_id, centroid in zip(face_ids, centroids_of_each_face): @@ -220,9 +218,7 @@ # Find a Named Selection with a prefix # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve a named selection whose name starts with a specific prefix -NSall = Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) my_nsel = [i for i in NSall if i.Name.startswith("b")][0] print(my_nsel.Name) @@ -275,9 +271,9 @@ # Create a new coordinate system csys = Model.CoordinateSystems.AddCoordinateSystem() # place csys origin at arbitrary (0,25,50) location -csys.SetOriginLocation(Quantity(0,"in"), Quantity(25,"in"), Quantity(50,"in")) +csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) # set primary X axis to arbitrary (1,2,3) direction -csys.PrimaryAxisDirection = Vector3D(1,2,3) +csys.PrimaryAxisDirection = Vector3D(1, 2, 3) # %% # Add a cartesian coordinate system at a location (0,25,50) inches with primary X axis towards an arbitrary (1,2,3) direction @@ -285,10 +281,9 @@ # Create a new coordinate system csys = Model.CoordinateSystems.AddCoordinateSystem() # place csys origin at arbitrary (0,25,50) location -csys.SetOriginLocation(Quantity(0,"in"), Quantity(25,"in"), Quantity(50,"in")) +csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) # set primary X axis to arbitrary (1,2,3) direction -csys.PrimaryAxisDirection = Vector3D(1,2,3) - +csys.PrimaryAxisDirection = Vector3D(1, 2, 3) # %% @@ -297,10 +292,9 @@ # Create a new coordinate system csys = app.Model.CoordinateSystems.AddCoordinateSystem() # place csys origin at arbitrary (0,25,50) location -csys.SetOriginLocation(Quantity(0,"in"), Quantity(25,"in"), Quantity(50,"in")) +csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) # set primary X axis to arbitrary (1,2,3) direction -csys.PrimaryAxisDirection = Vector3D(1,2,3) - +csys.PrimaryAxisDirection = Vector3D(1, 2, 3) # sphinx_gallery_start_ignore diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index 1b2cf3f9c..82addda6b 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -62,13 +62,11 @@ # Get information about all Contacts Defined # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all contact regions defined in the model -all_contacts = Model.Connections.GetChildren( - DataModelObjectCategory.ContactRegion, True -) +all_contacts = Model.Connections.GetChildren(DataModelObjectCategory.ContactRegion, True) # Print count of all contact regions numContacts = all_contacts.Count -print("There are %s contact regions" % (numContacts) ) +print("There are %s contact regions" % (numContacts)) # Print details of each contact region for contact in all_contacts: @@ -80,7 +78,6 @@ print("Target: ", contact.TargetBodies, list(contact.TargetLocation.Ids)) - # %% # Create Automatic Connections on a chosen named selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -94,9 +91,7 @@ contactgroup.InternalObject.DetectCylindricalFacesType = 1 # Retrieve a named selection for the connection group -NSall = Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) my_nsel = [i for i in NSall if i.Name == "bodies_5"][0] # Assign the named selection to the connection group and create automatic connections @@ -114,9 +109,7 @@ c1 = c.AddContactRegion() # Retrieve named selections for the source and target locations -NSall = Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) a = [i for i in NSall if i.Name == "block1_washer_cont"][0] c1.TargetLocation = a a = [i for i in NSall if i.Name == "block1_washer_targ"][0] @@ -128,12 +121,11 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ connections = Model.Connections fixed_joint = connections.AddJoint() -fixed_joint.ConnectionType=JointScopingType.BodyToGround +fixed_joint.ConnectionType = JointScopingType.BodyToGround fixed_joint.Type = JointType.Fixed fixed_joint.MobileLocation = app.DataModel.GetObjectsByName("block1_washer_cont")[0] - # %% # Insert a Joint using face IDs # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -165,7 +157,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ connections = Model.Connections spring = connections.AddSpring() -spring.ConnectionType=JointScopingType.BodyToGround +spring.ConnectionType = JointScopingType.BodyToGround spring.LongitudinalStiffness = Quantity(1, "N m^-1") spring.MobileScopingMethod = GeometryDefineByType.Component spring.MobileScopeLocation = app.DataModel.GetObjectsByName("block1_washer_cont")[0] @@ -193,9 +185,7 @@ brg.DampingC21.Output.DiscreteValues = [Quantity("121 [N sec m^-1]")] # Retrieve named selections for the reference and mobile locations -NSall = Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) brg.ReferenceLocation = [i for i in NSall if i.Name == "shank_surface"][0] brg.MobileLocation = [i for i in NSall if i.Name == "shank_surface"][0] diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index 46f8084bb..89b5699df 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -69,9 +69,7 @@ # Delete a named selection # ~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all named selections in the project -NSall = Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) # Delete a named selection by its name a = [i for i in NSall if i.Name == "Top_Face"][0] @@ -124,18 +122,17 @@ GenerationCriteria.Add(Criterion2) # Generate the named selection based on the criteria -NS1.Name="faces_for_support" +NS1.Name = "faces_for_support" NS1.Generate() - # %% # Extract all the details of a named selection worksheet named "faces_for_support" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NSall=app.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +NSall = app.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) my_nsel = [i for i in NSall if i.Name == "shaft"][0] worksheet = my_nsel.GenerationCriteria -for i in range(0,len(list(worksheet))): +for i in range(0, len(list(worksheet))): print(worksheet[i].Action) print(worksheet[i].EntityType) print(worksheet[i].Criterion) @@ -144,14 +141,11 @@ print(worksheet[i].CoordinateSystem.Name) - # %% # Find a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all named selections in the project -NSall = Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) # Find a specific named selection by its name a = [i for i in NSall if i.Name == "Rubber_Bodies30"][0] @@ -164,9 +158,7 @@ # Identify Named Selections based on Name and Type # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all named selections in the project -NSall = Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) # Filter named selections based on keywords in their names keywords = ["Rubber_Bodies30", "Inner_Faces30", "Outer_Faces30"] diff --git a/examples/00_setup/05_mesh.py b/examples/00_setup/05_mesh.py index c4b251d7d..2215ebc85 100644 --- a/examples/00_setup/05_mesh.py +++ b/examples/00_setup/05_mesh.py @@ -60,12 +60,11 @@ # %% # Set Global Mesh Settings # ~~~~~~~~~~~~~~~~~~~~~~~~ -mesh=Model.Mesh -mesh.ElementSize = Quantity('37 [mm]') +mesh = Model.Mesh +mesh.ElementSize = Quantity("37 [mm]") mesh.ElementOrder = ElementOrder.Linear - # %% # Insert a Local Meshing Control for a Named Selection # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index 69498e590..185b7e4f1 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -241,7 +241,11 @@ temp_bc = analysis2.AddTemperature() temp_bc.Location = app.DataModel.GetObjectsByName("fixed")[0] temp_bc.Magnitude.Output.DiscreteValues = [Quantity("22[C]"), Quantity("60[C]")] -temp_bc.Magnitude.Inputs[0].DiscreteValues = [Quantity("0 [sec]"), Quantity("1 [sec]"), Quantity("2 [sec]")] +temp_bc.Magnitude.Inputs[0].DiscreteValues = [ + Quantity("0 [sec]"), + Quantity("1 [sec]"), + Quantity("2 [sec]"), +] temp_bc.Magnitude.Output.DiscreteValues = [Quantity("22[C]"), Quantity("50[C]"), Quantity("80[C]")] @@ -259,11 +263,22 @@ if named_sel != None: convection.Location = named_sel -convection.AmbientTemperature.Inputs[0].DiscreteValues = [Quantity("0 [s]"), Quantity("1 [s]")] # Set the time values -convection.AmbientTemperature.Output.DiscreteValues = [Quantity('760 [C]'), Quantity('800 [C]')] # Set the Ambient Temperature values -convection.FilmCoefficient.Inputs[0].DiscreteValues = [Quantity("0 [s]"), Quantity("1 [s]")] # Set the time values -convection.FilmCoefficient.Output.DiscreteValues = [Quantity("100 [W m^-1 m^-1 K^-1]"), Quantity("150 [W m^-1 m^-1 K^-1]")] #Set the HTC values - +convection.AmbientTemperature.Inputs[0].DiscreteValues = [ + Quantity("0 [s]"), + Quantity("1 [s]"), +] # Set the time values +convection.AmbientTemperature.Output.DiscreteValues = [ + Quantity("760 [C]"), + Quantity("800 [C]"), +] # Set the Ambient Temperature values +convection.FilmCoefficient.Inputs[0].DiscreteValues = [ + Quantity("0 [s]"), + Quantity("1 [s]"), +] # Set the time values +convection.FilmCoefficient.Output.DiscreteValues = [ + Quantity("100 [W m^-1 m^-1 K^-1]"), + Quantity("150 [W m^-1 m^-1 K^-1]"), +] # Set the HTC values # %% @@ -326,37 +341,37 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ analysis_settings = Model.Analyses[0].AnalysisSettings analysis_settings.CurrentStepNumber = 1 -print(analysis_settings.AutomaticTimeStepping ) +print(analysis_settings.AutomaticTimeStepping) # %% # Set Step end time # ~~~~~~~~~~~~~~~~~ analysis_settings.CurrentStepNumber = 5 -analysis_settings.StepEndTime = Quantity('0.1 [sec]') +analysis_settings.StepEndTime = Quantity("0.1 [sec]") # %% # Define Load steps with end times # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -analysis_settings.NumberOfSteps=3 +analysis_settings.NumberOfSteps = 3 analysis_settings.CurrentStepNumber = 1 -analysis_settings.StepEndTime = Quantity('1.0 [sec]') +analysis_settings.StepEndTime = Quantity("1.0 [sec]") analysis_settings.CurrentStepNumber = 2 -analysis_settings.StepEndTime = Quantity('10.0 [sec]') +analysis_settings.StepEndTime = Quantity("10.0 [sec]") analysis_settings.CurrentStepNumber = 3 -analysis_settings.StepEndTime = Quantity('100.0 [sec]') +analysis_settings.StepEndTime = Quantity("100.0 [sec]") # %% # Define substep sizing using times # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ analysis_settings.CurrentStepNumber = 1 -analysis_settings.StepEndTime = Quantity('0.1 [sec]') -analysis_settings.AutomaticTimeStepping =analysis_settings.AutomaticTimeStepping.On -analysis_settings.DefineBy=analysis_settings.DefineBy.Time +analysis_settings.StepEndTime = Quantity("0.1 [sec]") +analysis_settings.AutomaticTimeStepping = analysis_settings.AutomaticTimeStepping.On +analysis_settings.DefineBy = analysis_settings.DefineBy.Time analysis_settings.InitialTimeStep = Quantity("0.005 [s]") analysis_settings.MaximumTimeStep = Quantity("0.5 [s]") analysis_settings.MinimumTimeStep = Quantity("0.0005 [s]") @@ -366,12 +381,12 @@ # Define substep sizing using steps # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ analysis_settings.CurrentStepNumber = 1 -analysis_settings.StepEndTime = Quantity('0.1 [sec]') -analysis_settings.AutomaticTimeStepping =analysis_settings.AutomaticTimeStepping.On -analysis_settings.DefineBy=analysis_settings.DefineBy.Substeps -analysis_settings.InitialSubsteps=15 -analysis_settings.MinimumSubsteps=5 -analysis_settings.MaximumSubsteps=50 +analysis_settings.StepEndTime = Quantity("0.1 [sec]") +analysis_settings.AutomaticTimeStepping = analysis_settings.AutomaticTimeStepping.On +analysis_settings.DefineBy = analysis_settings.DefineBy.Substeps +analysis_settings.InitialSubsteps = 15 +analysis_settings.MinimumSubsteps = 5 +analysis_settings.MaximumSubsteps = 50 # %% # Set Iterative solver type for solution @@ -415,14 +430,11 @@ # Set the step end time and time steps in Transient structural analysis # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # analysis = app.Model.AddTransientStructuralAnalysis() -analysis_settings=analysis.AnalysisSettings -analysis_settings.SetStepEndTime( 1, Quantity("0.4 [s]")) -analysis_settings.SetInitialTimeStep(1,Quantity("0.0001 [s]")) -analysis_settings.SetMinimumTimeStep(1,Quantity("0.0000001 [s]")) -analysis_settings.SetMaximumTimeStep(1,Quantity("0.01 [s]")) - - - +analysis_settings = analysis.AnalysisSettings +analysis_settings.SetStepEndTime(1, Quantity("0.4 [s]")) +analysis_settings.SetInitialTimeStep(1, Quantity("0.0001 [s]")) +analysis_settings.SetMinimumTimeStep(1, Quantity("0.0000001 [s]")) +analysis_settings.SetMaximumTimeStep(1, Quantity("0.01 [s]")) # sphinx_gallery_start_ignore diff --git a/examples/00_setup/08_tree_objects.py b/examples/00_setup/08_tree_objects.py index b53ed2a48..fc064d282 100644 --- a/examples/00_setup/08_tree_objects.py +++ b/examples/00_setup/08_tree_objects.py @@ -69,16 +69,14 @@ # %% # Print all visible properties of a tree # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -tree_object= DataModel.GetObjectsByName("Contact Region")[0] +tree_object = DataModel.GetObjectsByName("Contact Region")[0] for prop in tree_object.Properties: - print(f'{prop.Name}: {prop.InternalValue}') + print(f"{prop.Name}: {prop.InternalValue}") # or for tree_object in tree_object.VisibleProperties: print(tree_object.Caption + " | " + tree_object.StringValue) - - # %% # Accessing Mesh Data # ~~~~~~~~~~~~~~~~~~~ @@ -103,9 +101,7 @@ # Retrieve all contact regions abc = DataModel.GetObjectsByType(DataModelObjectCategory.ContactRegion) -all_contacts = Model.Connections.GetChildren( - DataModelObjectCategory.ContactRegion, True -) +all_contacts = Model.Connections.GetChildren(DataModelObjectCategory.ContactRegion, True) # Access a specific contact region by name my_contact = [contact for contact in all_contacts if contact.Name == "Contact Region"][0] @@ -121,12 +117,8 @@ all_contacts2 = Model.Connections.GetChildren[ Ansys.ACT.Automation.Mechanical.Connections.ContactRegion ](True) -all_remote_points2 = Model.GetChildren[ - Ansys.ACT.Automation.Mechanical.RemotePoint -](True) -all_folders = Model.GetChildren[ - Ansys.ACT.Automation.Mechanical.TreeGroupingFolder -](True) +all_remote_points2 = Model.GetChildren[Ansys.ACT.Automation.Mechanical.RemotePoint](True) +all_folders = Model.GetChildren[Ansys.ACT.Automation.Mechanical.TreeGroupingFolder](True) # %% # Finding Duplicate Objects by Name @@ -207,9 +199,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Access specific named selections by their names. -NSall = Model.NamedSelections.GetChildren[ - Ansys.ACT.Automation.Mechanical.NamedSelection -](True) +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) my_nsel = [i for i in NSall if i.Name.startswith("NSF")][0] my_nsel2 = [i for i in NSall if i.Name == "NSInsideFaces"][0] @@ -228,7 +218,6 @@ all_pm = [i for i in all_pm if not i.Suppressed] - # sphinx_gallery_start_ignore # Save the Mechanical database file from pathlib import Path From cf56b8cd4a6c09e100af22a73040f0ea9ba1ed06 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 6 Oct 2025 08:11:09 -0500 Subject: [PATCH 30/52] update files --- examples/00_setup/01_setup.py | 6 +++++- examples/00_setup/02_geometry.py | 2 +- examples/00_setup/03_connections.py | 4 +++- examples/00_setup/04_named_selections.py | 7 ++++++- examples/00_setup/05_mesh.py | 3 ++- examples/00_setup/06_loads.py | 2 +- examples/00_setup/07_results.py | 3 ++- examples/00_setup/08_tree_objects.py | 18 +++++++++++------- examples/00_setup/readme.txt | 4 +++- 9 files changed, 34 insertions(+), 15 deletions(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index d77ecda1e..370babb8a 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -25,7 +25,11 @@ App --- -This section has helper scripts for Embedded App +This section has helper scripts to start an embedded instance of Mechanical Application and import/open a file . + +This is a prerequisite step for the other helper scripts in the following pages. + + """ # %% diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index b0b13affe..fbe895daa 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -25,7 +25,7 @@ Geometry -------- -This section contains utility scripts for working with Geometry, including importing, analyzing, and accessing geometric data, as well as utilizing it for downstream preprocessing operations in Mechanical simulations. Coordinate Systems too are covered here. +This section contains a few utility scripts for working with Geometry, including importing, analyzing, and accessing geometric data, as well as utilizing it for downstream preprocessing operations in Mechanical simulations. Coordinate Systems too are covered here. """ # %% diff --git a/examples/00_setup/03_connections.py b/examples/00_setup/03_connections.py index 82addda6b..eac87ddb1 100644 --- a/examples/00_setup/03_connections.py +++ b/examples/00_setup/03_connections.py @@ -25,7 +25,9 @@ Connections ----------- -This section has helper scripts for Connections. + +This section contains a few utility scripts for working with Connections. + """ # sphinx_gallery_start_ignore diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index 89b5699df..bebbdcc82 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -25,7 +25,7 @@ Named Selections ---------------- -This section has helper scripts for Named Selections. +This section contains a few utility scripts for creating , finding and using Named Selections. """ # sphinx_gallery_start_ignore @@ -129,8 +129,13 @@ # %% # Extract all the details of a named selection worksheet named "faces_for_support" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +<<<<<<< HEAD +NSall=app.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +my_nsel = [i for i in NSall if i.Name == "faces_for_support"][0] +======= NSall = app.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) my_nsel = [i for i in NSall if i.Name == "shaft"][0] +>>>>>>> 8aacf8ab962a5255ace7487b5710c04c4ca8c86b worksheet = my_nsel.GenerationCriteria for i in range(0, len(list(worksheet))): print(worksheet[i].Action) diff --git a/examples/00_setup/05_mesh.py b/examples/00_setup/05_mesh.py index 2215ebc85..492cf3c64 100644 --- a/examples/00_setup/05_mesh.py +++ b/examples/00_setup/05_mesh.py @@ -25,7 +25,8 @@ Mesh ---- -This section has helper scripts for Named Selections. +This section contains a few utility scripts for setting local and global Mesh Controls. + """ # sphinx_gallery_start_ignore diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index 185b7e4f1..4d2daae37 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -25,7 +25,7 @@ Loads and BCs ------------- -This script contains helper examples for applying loads and boundary conditions in Ansys Mechanical. +This script contains helper examples for applying loads and boundary conditions in Ansys Mechanical. Analysis Settings too are covered here. """ # sphinx_gallery_start_ignore diff --git a/examples/00_setup/07_results.py b/examples/00_setup/07_results.py index 02dbb13d7..8b04c4aa2 100644 --- a/examples/00_setup/07_results.py +++ b/examples/00_setup/07_results.py @@ -25,7 +25,8 @@ Results ------- -This section has helper scripts for Results. +This section contains a few utility scripts for result objects. + """ # sphinx_gallery_start_ignore diff --git a/examples/00_setup/08_tree_objects.py b/examples/00_setup/08_tree_objects.py index fc064d282..03d610a51 100644 --- a/examples/00_setup/08_tree_objects.py +++ b/examples/00_setup/08_tree_objects.py @@ -25,7 +25,8 @@ Tree Objects ------------ -This section has helper scripts for Tree Objects. +This section contains a few utility scripts for working with Tree Objects. + """ # sphinx_gallery_start_ignore @@ -66,6 +67,8 @@ body = DataModel.GeoData.GeoEntityById(312) +<<<<<<< HEAD +======= # %% # Print all visible properties of a tree # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -75,6 +78,7 @@ # or for tree_object in tree_object.VisibleProperties: print(tree_object.Caption + " | " + tree_object.StringValue) +>>>>>>> 8aacf8ab962a5255ace7487b5710c04c4ca8c86b # %% @@ -87,7 +91,7 @@ # %% # Accessing All Objects and Child Objects -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Examples of accessing all objects, bodies, named selections, and contact regions. # Retrieve all objects in the tree @@ -122,7 +126,7 @@ # %% # Finding Duplicate Objects by Name -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Identify duplicate objects in the project tree based on their names. import collections @@ -145,7 +149,7 @@ # %% # Using DataObjects and GetByName -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Access specific data objects by their names. c1 = "Solution" @@ -154,7 +158,7 @@ # %% # Using DataObjects, NamesByType, and GetByName -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Access and filter contact regions based on their properties. new_contact_list = [] @@ -190,13 +194,13 @@ # %% # Using GetObjectsByName -# ~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~ # Access a specific object by its name. bb = DataModel.GetObjectsByName("Connector\Solid1")[0] # %% # Accessing a Named Selection -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Access specific named selections by their names. NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) diff --git a/examples/00_setup/readme.txt b/examples/00_setup/readme.txt index 5769a4c43..cc85d5066 100644 --- a/examples/00_setup/readme.txt +++ b/examples/00_setup/readme.txt @@ -1,4 +1,6 @@ Setup ----- -Set up Embedding and configure + +This directory contains a collection of helper scripts for Embedded Instance of PyMechanical.Each script focuses on a specific stage in the Ansys Mechanical workflow, providing utility and automation for common tasks. + From 0de3dc13fdc46f615d8e2533ab3098d11bc15fd0 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 6 Oct 2025 08:28:44 -0500 Subject: [PATCH 31/52] fix conflicts --- .pre-commit-config.yaml | 2 +- examples/00_setup/01_setup.py | 3 ++- examples/00_setup/02_geometry.py | 11 +++++++---- examples/00_setup/04_named_selections.py | 8 ++------ examples/00_setup/06_loads.py | 3 ++- examples/00_setup/08_tree_objects.py | 13 ------------- examples/00_setup/out/test.mechdat | Bin 4766920 -> 0 bytes 7 files changed, 14 insertions(+), 26 deletions(-) delete mode 100644 examples/00_setup/out/test.mechdat diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6302e4f27..f58936e6b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: rev: 1.20.0 hooks: - id: blacken-docs - additional_dependencies: [black==24.10.0] + additional_dependencies: [black==25.9.0] - repo: https://github.com/pycqa/isort rev: 6.0.1 diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 370babb8a..b967c6eb4 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -25,7 +25,8 @@ App --- -This section has helper scripts to start an embedded instance of Mechanical Application and import/open a file . +This section has helper scripts to start an embedded instance of Mechanical +Application and import/open a file. This is a prerequisite step for the other helper scripts in the following pages. diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index fbe895daa..fa78225d0 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -25,7 +25,10 @@ Geometry -------- -This section contains a few utility scripts for working with Geometry, including importing, analyzing, and accessing geometric data, as well as utilizing it for downstream preprocessing operations in Mechanical simulations. Coordinate Systems too are covered here. +This section contains a few utility scripts for working with Geometry, +including importing, analyzing, and accessing geometric data, as well +as utilizing it for downstream preprocessing operations in Mechanical +simulations. Coordinate Systems too are covered here. """ # %% @@ -276,9 +279,9 @@ csys.PrimaryAxisDirection = Vector3D(1, 2, 3) # %% -# Add a cartesian coordinate system at a location (0,25,50) inches with primary X axis towards an arbitrary (1,2,3) direction -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a new coordinate system +# Add a cartesian coordinate system at a location (0,25,50) inches +# with primary X axis towards an arbitrary (1,2,3) direction +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ csys = Model.CoordinateSystems.AddCoordinateSystem() # place csys origin at arbitrary (0,25,50) location csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) diff --git a/examples/00_setup/04_named_selections.py b/examples/00_setup/04_named_selections.py index bebbdcc82..ce45ce48b 100644 --- a/examples/00_setup/04_named_selections.py +++ b/examples/00_setup/04_named_selections.py @@ -129,13 +129,9 @@ # %% # Extract all the details of a named selection worksheet named "faces_for_support" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -<<<<<<< HEAD -NSall=app.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) -my_nsel = [i for i in NSall if i.Name == "faces_for_support"][0] -======= NSall = app.Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) -my_nsel = [i for i in NSall if i.Name == "shaft"][0] ->>>>>>> 8aacf8ab962a5255ace7487b5710c04c4ca8c86b +my_nsel = [i for i in NSall if i.Name == "faces_for_support"][0] + worksheet = my_nsel.GenerationCriteria for i in range(0, len(list(worksheet))): print(worksheet[i].Action) diff --git a/examples/00_setup/06_loads.py b/examples/00_setup/06_loads.py index 4d2daae37..6fcd70b9d 100644 --- a/examples/00_setup/06_loads.py +++ b/examples/00_setup/06_loads.py @@ -25,7 +25,8 @@ Loads and BCs ------------- -This script contains helper examples for applying loads and boundary conditions in Ansys Mechanical. Analysis Settings too are covered here. +This script contains helper examples for applying loads and boundary +conditions in Ansys Mechanical. Analysis Settings too are covered here. """ # sphinx_gallery_start_ignore diff --git a/examples/00_setup/08_tree_objects.py b/examples/00_setup/08_tree_objects.py index 03d610a51..92e337182 100644 --- a/examples/00_setup/08_tree_objects.py +++ b/examples/00_setup/08_tree_objects.py @@ -67,19 +67,6 @@ body = DataModel.GeoData.GeoEntityById(312) -<<<<<<< HEAD -======= -# %% -# Print all visible properties of a tree -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -tree_object = DataModel.GetObjectsByName("Contact Region")[0] -for prop in tree_object.Properties: - print(f"{prop.Name}: {prop.InternalValue}") -# or -for tree_object in tree_object.VisibleProperties: - print(tree_object.Caption + " | " + tree_object.StringValue) ->>>>>>> 8aacf8ab962a5255ace7487b5710c04c4ca8c86b - # %% # Accessing Mesh Data diff --git a/examples/00_setup/out/test.mechdat b/examples/00_setup/out/test.mechdat deleted file mode 100644 index aa09906c89176a3fa73d19879fae04fae0b2e48b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4766920 zcmeF$30zOx{`mi0q0A{Nks=~Oljbs(L`9hrMJYl`iB!r^nIcm}nPpBAGNnYyR2&ge z86spZLqfk#ed?TZ&%NLK``_Q=@&7#@zjI&PqrKK%`@PnBujgKS%Q-8ohgh|2rrb=Z zJ!E8rMuKczwc%7#f8?CEu4`(zZn!_Wz9LayF0U^SNQx^GLhTAJ zS_*=c&@g^OS>H|2ZX~W5)i=aCsnykD>#uM5^r)-J)L&Ely#%Z+2ac>=QAYi~%BbIP z<9C?VE%bldXG%TA``JiKT>ejSMuu(c#u;xcF6%BtCka8iZvTo;wb$aEEFn>!K>faK z*soHe{at&fb~bT@ctJehA14#j@P_~E@X7UY*4xF;{a;53!lL>(rQQENZfAYm z@{}R}(@=Ho4OzWZ5G()N;QtRdYrl83d$D2PG?aqq3;eH+11MgRc> z5I_KdzkxuIXbrkTi0H>a=p*RV)wJub)C7n6YXi~mbULCRZPDFg?@D{hJuOcT2FNDCmK;au9oO-?U?<9+FEU0OB56GH_&4V2q1s}0tg_0 z00IagfB*srAbe?lxBbOXhQ%21Q0*~f&aG!CX4>M50pq7YwOd&QYrM#Z-c5LH~F+O_Z1E%dwM4sHkEtO z_0*WXZ96Bd4nLbS;i2=x8E;PBTVrihC9M`Jge~bM-ReSx)M@{xN*|>kFYtU3&{2A8 z^VdUCQu3nxjQ;V ze}8ps+ncED&vUnGR4?dmZZpqn!<}L4KRrW@zqmhiE!S#|)vo6@JdR3&`E7;EU zTDA3ONezc9ZyaRhQe<HT%1+9`24b~6UM90{3dMZ7qa}SvPEWP zzrv+my%p2@jLm6rWXYIL9Tn|=vzs^H@cnkl!iyu~JJ!6rnPzr9Zh>*1vhMO0zv30T z6gIKTEi~%$Vocu`CttVg>z8#gN74NKz}%%6X6485iE%|5L%b{Z#p0 z(>%ZBc@1_x?(MyGvdkp_VL|ILtREJ9PnbY<&Wth zWA1GlXr%h$ng6GaVG0S?8v9S(Uj1bJq%D)2bHbL~oBcWY^U|tk*>@s;KA(8+c38ml zHU3o(zLY3!boH?Bu&wYzpWIJjE%ST$oG{3}9Qwm-xmC9#v9b!uL&wN}(l%>mo8$iR zfajo3<)fw!8dBLqSEIDO(WJJqvOX)XX_P()RQdGrzWE@F?TK%XtI618?LX(bssG@C z{=E*3HXLqyqewXOqS9+@=JA6PH#;8k-l}|~x5<(44jNBG4@wp4w`uQtAhJgCey>iA zHQd62M;o-Mn$x41?PbI085(Yf1KVy{{_|a%PsuT6gDgT#zgO5FbRVxLF(rFru!_>Y zWkV;A*Sjd!V&*=ph!!(7)U-z|iFa)jS=BjMbgFnN>gF>}$+LNq_KoHd7Hg*bYGg7b za={r{>=8f!0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 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 zctv{kiho2qibfW{Pk)SGn^B)X^=Wul{yf8MQ6~S`OB&|8a(Y-KXKL zYgmK0PwhStufj{D^^Z@o-#@MUk3J1^)b`*&009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** 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 zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0tCLh 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 z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t9LW%1cX15c4+>6EDvPV^)0I$m5PF4mwsMmMR630_m|yeZQ(tm*>u;s_UhYQl$Vy2B*JR(dE+q% zH@~y?)ROpc@oXk9-d7wo5+Fc;009DZOJKL~IL~aTTW4|_0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7{<9rA761SM02t(NJ%`YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r4E%ur DE6~0o From 990f8052b6ef170860fbf56c1ad050c4b2e6e9ad Mon Sep 17 00:00:00 2001 From: rs-bh-n Date: Tue, 7 Oct 2025 22:31:57 +0530 Subject: [PATCH 32/52] app removed in setup.py for extapi --- examples/00_setup/01_setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index b967c6eb4..47da7be1b 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -80,9 +80,9 @@ # Set Units # ~~~~~~~~~~~~~~~~~~~~~~~ -app.ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM -app.ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian -app.ExtAPI.Application.ActiveAngularVelocityUnit = AngularVelocityUnitType.RadianPerSecond +ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM +ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian +ExtAPI.Application.ActiveAngularVelocityUnit = AngularVelocityUnitType.RadianPerSecond # %% # View messages in Mechanical using PyMechanical From c43de28ccbb40c75ee6e6e720593f5c91ffaf374 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Tue, 28 Oct 2025 13:18:41 -0400 Subject: [PATCH 33/52] trace memory --- examples/00_setup/01_setup.py | 53 +++++- examples/00_setup/01_setup2.py | 171 ++++++++++++++++++ examples/00_setup/01_setup3.py | 171 ++++++++++++++++++ .../00_setup => examples_save}/02_geometry.py | 0 .../03_connections.py | 0 .../04_named_selections.py | 0 .../00_setup => examples_save}/05_mesh.py | 0 .../00_setup => examples_save}/06_loads.py | 0 .../00_setup => examples_save}/07_results.py | 0 .../08_tree_objects.py | 0 10 files changed, 394 insertions(+), 1 deletion(-) create mode 100644 examples/00_setup/01_setup2.py create mode 100644 examples/00_setup/01_setup3.py rename {examples/00_setup => examples_save}/02_geometry.py (100%) rename {examples/00_setup => examples_save}/03_connections.py (100%) rename {examples/00_setup => examples_save}/04_named_selections.py (100%) rename {examples/00_setup => examples_save}/05_mesh.py (100%) rename {examples/00_setup => examples_save}/06_loads.py (100%) rename {examples/00_setup => examples_save}/07_results.py (100%) rename {examples/00_setup => examples_save}/08_tree_objects.py (100%) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 47da7be1b..dbea00565 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -33,6 +33,11 @@ """ +import tracemalloc + +# Start tracing memory +tracemalloc.start() + # %% # Create an embedded instance and open an existing Mechanical File # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -42,12 +47,21 @@ mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + # The following line creates an instance of the app, extracts the global API entry points, # and merges them into your Python global variables. app = App(db_file=mechdat_path, globals=globals()) print(app) +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") # Alternatively, you can use the update_globals method of the App class to # update the global variables.The second argument, if set to False updates @@ -66,6 +80,11 @@ app.new() # sphinx_gallery_end_ignore +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic @@ -76,6 +95,10 @@ geometry_import_preferences.ProcessMaterialProperties = True geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") # %% # Set Units # ~~~~~~~~~~~~~~~~~~~~~~~ @@ -84,13 +107,20 @@ ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian ExtAPI.Application.ActiveAngularVelocityUnit = AngularVelocityUnitType.RadianPerSecond +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") # %% # View messages in Mechanical using PyMechanical # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ app.messages.show() - +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") # %% # Plot and Print the Tree (To check model so far) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -98,9 +128,18 @@ # Plot app.plot() +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + # Print the tree app.print_tree() +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") # %% # Save the model @@ -111,6 +150,10 @@ test_mechdat_path = str(output_path / "test.mechdat") app.save_as(test_mechdat_path, overwrite=True) +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") # sphinx_gallery_start_ignore # Close the app @@ -118,3 +161,11 @@ # Delete the downloaded files delete_downloads() # sphinx_gallery_end_ignore + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# stop tracing memory +tracemalloc.stop() diff --git a/examples/00_setup/01_setup2.py b/examples/00_setup/01_setup2.py new file mode 100644 index 000000000..dbea00565 --- /dev/null +++ b/examples/00_setup/01_setup2.py @@ -0,0 +1,171 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +""".. _ref_setup: + +App +--- + +This section has helper scripts to start an embedded instance of Mechanical +Application and import/open a file. + +This is a prerequisite step for the other helper scripts in the following pages. + + +""" + +import tracemalloc + +# Start tracing memory +tracemalloc.start() + +# %% +# Create an embedded instance and open an existing Mechanical File +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file + +mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# The following line creates an instance of the app, extracts the global API entry points, +# and merges them into your Python global variables. + +app = App(db_file=mechdat_path, globals=globals()) +print(app) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Alternatively, you can use the update_globals method of the App class to +# update the global variables.The second argument, if set to False updates +# globals without enums like "SelectionTypeEnum" or "LoadDefineBy" +# app = App() +# app.update_globals(globals(), False) + +# For a specific version , use ; +# app = App(version=241) + +# %% +# Import a Geometry File +# ~~~~~~~~~~~~~~~~~~~~~~ + +# sphinx_gallery_start_ignore +app.new() +# sphinx_gallery_end_ignore + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") +# %% +# Set Units +# ~~~~~~~~~~~~~~~~~~~~~~~ + +ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM +ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian +ExtAPI.Application.ActiveAngularVelocityUnit = AngularVelocityUnitType.RadianPerSecond + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") +# %% +# View messages in Mechanical using PyMechanical +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +app.messages.show() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") +# %% +# Plot and Print the Tree (To check model so far) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Plot +app.plot() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Print the tree +app.print_tree() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Save the model +# ~~~~~~~~~~~~~~~ +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +app.save_as(test_mechdat_path, overwrite=True) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# sphinx_gallery_start_ignore +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# stop tracing memory +tracemalloc.stop() diff --git a/examples/00_setup/01_setup3.py b/examples/00_setup/01_setup3.py new file mode 100644 index 000000000..dbea00565 --- /dev/null +++ b/examples/00_setup/01_setup3.py @@ -0,0 +1,171 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +""".. _ref_setup: + +App +--- + +This section has helper scripts to start an embedded instance of Mechanical +Application and import/open a file. + +This is a prerequisite step for the other helper scripts in the following pages. + + +""" + +import tracemalloc + +# Start tracing memory +tracemalloc.start() + +# %% +# Create an embedded instance and open an existing Mechanical File +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file + +mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# The following line creates an instance of the app, extracts the global API entry points, +# and merges them into your Python global variables. + +app = App(db_file=mechdat_path, globals=globals()) +print(app) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Alternatively, you can use the update_globals method of the App class to +# update the global variables.The second argument, if set to False updates +# globals without enums like "SelectionTypeEnum" or "LoadDefineBy" +# app = App() +# app.update_globals(globals(), False) + +# For a specific version , use ; +# app = App(version=241) + +# %% +# Import a Geometry File +# ~~~~~~~~~~~~~~~~~~~~~~ + +# sphinx_gallery_start_ignore +app.new() +# sphinx_gallery_end_ignore + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") +# %% +# Set Units +# ~~~~~~~~~~~~~~~~~~~~~~~ + +ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM +ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian +ExtAPI.Application.ActiveAngularVelocityUnit = AngularVelocityUnitType.RadianPerSecond + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") +# %% +# View messages in Mechanical using PyMechanical +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +app.messages.show() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") +# %% +# Plot and Print the Tree (To check model so far) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Plot +app.plot() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Print the tree +app.print_tree() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Save the model +# ~~~~~~~~~~~~~~~ +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +app.save_as(test_mechdat_path, overwrite=True) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# sphinx_gallery_start_ignore +# Close the app +app.close() +# Delete the downloaded files +delete_downloads() +# sphinx_gallery_end_ignore + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# stop tracing memory +tracemalloc.stop() diff --git a/examples/00_setup/02_geometry.py b/examples_save/02_geometry.py similarity index 100% rename from examples/00_setup/02_geometry.py rename to examples_save/02_geometry.py diff --git a/examples/00_setup/03_connections.py b/examples_save/03_connections.py similarity index 100% rename from examples/00_setup/03_connections.py rename to examples_save/03_connections.py diff --git a/examples/00_setup/04_named_selections.py b/examples_save/04_named_selections.py similarity index 100% rename from examples/00_setup/04_named_selections.py rename to examples_save/04_named_selections.py diff --git a/examples/00_setup/05_mesh.py b/examples_save/05_mesh.py similarity index 100% rename from examples/00_setup/05_mesh.py rename to examples_save/05_mesh.py diff --git a/examples/00_setup/06_loads.py b/examples_save/06_loads.py similarity index 100% rename from examples/00_setup/06_loads.py rename to examples_save/06_loads.py diff --git a/examples/00_setup/07_results.py b/examples_save/07_results.py similarity index 100% rename from examples/00_setup/07_results.py rename to examples_save/07_results.py diff --git a/examples/00_setup/08_tree_objects.py b/examples_save/08_tree_objects.py similarity index 100% rename from examples/00_setup/08_tree_objects.py rename to examples_save/08_tree_objects.py From 388fe428cbf23e3c2dcc273376e81ce58c810023 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Tue, 28 Oct 2025 13:23:38 -0400 Subject: [PATCH 34/52] only run doc-build --- .github/workflows/ci_cd.yml | 1458 +++++++++++++++++------------------ 1 file changed, 729 insertions(+), 729 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index a4e3b053d..716d68fb8 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -42,80 +42,80 @@ concurrency: cancel-in-progress: true jobs: - update-changelog: - name: "Update CHANGELOG for new tag" - if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - steps: - - uses: ansys/actions/doc-deploy-changelog@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} - bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} - bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} - - style: - name: Code style - runs-on: ubuntu-latest - steps: - - name: PyAnsys code style checks - uses: ansys/actions/code-style@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - doc-style: - name: Documentation Style Check - runs-on: ubuntu-latest - steps: - - name: PyAnsys documentation style checks - uses: ansys/actions/doc-style@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - vulnerabilities: - name: Vulnerabilities - runs-on: ubuntu-latest - steps: - - name: PyAnsys Vulnerability check (on main) - if: github.ref == 'refs/heads/main' - uses: ansys/actions/check-vulnerabilities@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - python-package-name: ${{ env.PACKAGE_NAME }} - token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} - - - name: PyAnsys Vulnerability check (on dev mode) - if: github.ref != 'refs/heads/main' - uses: ansys/actions/check-vulnerabilities@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - python-package-name: ${{ env.PACKAGE_NAME }} - token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} - dev-mode: true - - smoke-tests: - name: Build and Smoke tests - runs-on: ${{ matrix.os }} - needs: [style] - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ['3.10', '3.11', '3.12', '3.13'] - should-release: - - ${{ github.event_name == 'push' && contains(github.ref, 'refs/tags') }} - exclude: - - should-release: false - os: macos-latest - steps: - - name: Build wheelhouse and perform smoke test - uses: ansys/actions/build-wheelhouse@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - library-name: ${{ env.PACKAGE_NAME }} - operating-system: ${{ matrix.os }} - python-version: ${{ matrix.python-version }} + # update-changelog: + # name: "Update CHANGELOG for new tag" + # if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + # runs-on: ubuntu-latest + # permissions: + # contents: write + # pull-requests: write + # steps: + # - uses: ansys/actions/doc-deploy-changelog@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} + # bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} + # bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} + + # style: + # name: Code style + # runs-on: ubuntu-latest + # steps: + # - name: PyAnsys code style checks + # uses: ansys/actions/code-style@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # python-version: ${{ env.MAIN_PYTHON_VERSION }} + + # doc-style: + # name: Documentation Style Check + # runs-on: ubuntu-latest + # steps: + # - name: PyAnsys documentation style checks + # uses: ansys/actions/doc-style@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + + # vulnerabilities: + # name: Vulnerabilities + # runs-on: ubuntu-latest + # steps: + # - name: PyAnsys Vulnerability check (on main) + # if: github.ref == 'refs/heads/main' + # uses: ansys/actions/check-vulnerabilities@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # python-version: ${{ env.MAIN_PYTHON_VERSION }} + # python-package-name: ${{ env.PACKAGE_NAME }} + # token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} + + # - name: PyAnsys Vulnerability check (on dev mode) + # if: github.ref != 'refs/heads/main' + # uses: ansys/actions/check-vulnerabilities@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # python-version: ${{ env.MAIN_PYTHON_VERSION }} + # python-package-name: ${{ env.PACKAGE_NAME }} + # token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} + # dev-mode: true + + # smoke-tests: + # name: Build and Smoke tests + # runs-on: ${{ matrix.os }} + # needs: [style] + # strategy: + # fail-fast: false + # matrix: + # os: [ubuntu-latest, windows-latest, macos-latest] + # python-version: ['3.10', '3.11', '3.12', '3.13'] + # should-release: + # - ${{ github.event_name == 'push' && contains(github.ref, 'refs/tags') }} + # exclude: + # - should-release: false + # os: macos-latest + # steps: + # - name: Build wheelhouse and perform smoke test + # uses: ansys/actions/build-wheelhouse@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # library-name: ${{ env.PACKAGE_NAME }} + # operating-system: ${{ matrix.os }} + # python-version: ${{ matrix.python-version }} revn-variations: name: Save variations of revn @@ -157,413 +157,413 @@ jobs: # PRs and merges use STABLE_REVN # Workflow dispatch can use any revision number - test-container-info: - name: Get SHA of test container - runs-on: public-ubuntu-latest-8-cores - needs: [revn-variations] - outputs: - sha: ${{ steps.get_sha.outputs.sha }} - strategy: - matrix: - test_container: ['${{ needs.revn-variations.outputs.test_container }}'] - steps: - - name: Login in Github Container registry - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Pull, launch, and validate Mechanical service - id: get_sha - env: - MECHANICAL_IMAGE: ${{ matrix.test_container }} - run: | - # Install jq for parsing JSON - pip install jq - - # Get docker info - image_info=$(docker manifest inspect -v ${{ env.MECHANICAL_IMAGE }}) # --format ".Descriptor.digest" - - # Get digest SHA - digest=$(echo "$image_info" | jq -r '.Descriptor.digest') - - # Remove the "sha256:" prefix to get only the SHA - sha="${digest#*:}" - echo "SHA of image ${{ env.MECHANICAL_IMAGE }} is $sha" - echo "sha=$sha" >> $GITHUB_OUTPUT - - config-matrix: - runs-on: ubuntu-latest - needs: [revn-variations] - outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} - steps: - - id: set-matrix - run: | - # if a tag(release) is pushed, test all versions - if ${{ github.event_name == 'push' }} && ${{ contains(github.ref, 'refs/tags') }}; then - echo "matrix={\"mechanical-version\":['24.1.0', '24.2.0', '25.1.0', '25.2.0'],\"experimental\":[false]}" >> $GITHUB_OUTPUT - else - echo "matrix={\"mechanical-version\":['${{ needs.revn-variations.outputs.test_docker_image_version }}'],\"experimental\":[false]}" >> $GITHUB_OUTPUT - fi - - container-stability-check: - runs-on: ubuntu-latest - needs: [revn-variations] - outputs: - container_stable_exit: ${{ steps.check_stability.outputs.container_stable_exit }} - steps: - - id: check_stability - run: | - sudo apt update - sudo apt install bc -y - container_version=$(echo "${{ needs.revn-variations.outputs.test_docker_image_version }}" | grep -o -E '[0-9]+(\.[0-9]+)?' | head -n 1) - if (( $(echo "$container_version > 24.2" | bc -l) )); then - echo "container_stable_exit=true" >> $GITHUB_OUTPUT - else - echo "container_stable_exit=false" >> $GITHUB_OUTPUT - fi - - remote-connect: - name: Remote connect testing and coverage - Mechanical ${{ matrix.mechanical-version }} - runs-on: public-ubuntu-latest-8-cores - needs: [style, revn-variations, config-matrix] - continue-on-error: ${{ matrix.experimental }} - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.config-matrix.outputs.matrix) }} - steps: - - name: Login in Github Container registry - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Pull, launch, and validate Mechanical service - env: - MECHANICAL_IMAGE: ${{ env.DOCKER_PACKAGE }}:${{ matrix.mechanical-version }} - # ANSYS_WORKBENCH_LOGGING_CONSOLE: 0 - # ANSYS_WORKBENCH_LOGGING_DIRECTORY: /log_file # workbench.log file - ANSYS_WORKBENCH_LOGGING_AUTO_FLUSH: 0 # turn off autoflush for faster performance - run: | - docker pull ${{ env.MECHANICAL_IMAGE }} - - echo "Run docker in detached mode" - docker run -d --name ${{ env.DOCKER_MECH_CONTAINER_NAME }} -e ANSYSLMD_LICENSE_FILE=1055@${{ env.LICENSE_SERVER }} -p ${{ env.PYMECHANICAL_PORT }}:10000 ${{ env.MECHANICAL_IMAGE }} - - # Wait for Mechanical to initialize with intelligent polling - max_wait=300 # Maximum wait time in seconds - check_interval=10 # Check every 10 seconds - elapsed=0 - - echo "Waiting for Mechanical to initialize..." - while [ $elapsed -lt $max_wait ]; do - docker logs ${{ env.DOCKER_MECH_CONTAINER_NAME }} > log.txt - if grep -q 'WB Initialize Done' log.txt 2>/dev/null; then - echo "Mechanical initialized successfully after ${elapsed} seconds" - break - fi - echo "Waiting for initialization... (${elapsed}/${max_wait}s)" - sleep $check_interval - elapsed=$((elapsed + check_interval)) - done - - # Final check - docker logs ${{ env.DOCKER_MECH_CONTAINER_NAME }} > log.txt - if ! grep -q 'WB Initialize Done' log.txt 2>/dev/null; then - echo "ERROR: Mechanical failed to initialize within ${max_wait} seconds" - echo "=== Last 50 lines of log.txt ===" - tail -n 50 log.txt || echo "No log file found" - exit 1 - fi - - - name: Display info - if: github.event_name == 'schedule' - id: capture_info - run: | - IMAGE_NAME=${{ env.DOCKER_PACKAGE }}:${{ matrix.mechanical-version }} - BUILD_DATE=$(docker run --rm --entrypoint head $IMAGE_NAME -n 1 /install/ansys_inc/v${{ needs.revn-variations.outputs.test_revn }}/aisol/CommonFiles/builddate.txt) - PUSHED_AT=$(docker inspect --format='{{.Created}}' $IMAGE_NAME) - echo "docker_info=$IMAGE_NAME was pushed at: $PUSHED_AT" >> $GITHUB_OUTPUT - echo "::group::Docker Info" - echo "docker_info=$PUSHED_AT" >> $GITHUB_OUTPUT - echo "build_info=$BUILD_DATE" >> $GITHUB_OUTPUT - echo "$IMAGE_NAME pushed at $PUSHED_AT" - echo "Build date : $BUILD_DATE" - echo "::endgroup::" - - - name: Testing - uses: ansys/actions/tests-pytest@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - pytest-markers: '-m remote_session_connect' - pytest-extra-args: '-s --junitxml remote_results${{ env.MAIN_PYTHON_VERSION}}.xml' - - - name: Publish Test Report - uses: mikepenz/action-junit-report@5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4 # v6.0.0 - if: always() - with: - report_paths: '**/remote_results*.xml' - check_name: Remote Connect Test Report ${{ env.MAIN_PYTHON_VERSION}} - detailed_summary: true - include_passed: true - fail_on_failure: true - - - name: Upload coverage results - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: matrix.mechanical-version == needs.revn-variations.outputs.test_docker_image_version - with: - include-hidden-files: true - name: coverage-tests - path: .cov - retention-days: 7 - - - name: Upload coverage results (as .coverage) - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: matrix.mechanical-version == needs.revn-variations.outputs.test_docker_image_version - with: - include-hidden-files: true - name: coverage-file-tests - path: .coverage - retention-days: 7 - - - name: Get Mechanical container logs - if: always() - run: | - docker logs ${{ env.DOCKER_MECH_CONTAINER_NAME }} > mechanical_tests_log-${{ matrix.mechanical-version }}.txt 2>&1 - echo CONTAINER LOGS OUTPUT - cat mechanical_tests_log-${{ matrix.mechanical-version }}.txt - echo CPU info - lscpu - - - name: Upload container logs - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: mechanical_tests_log-${{ matrix.mechanical-version }} - path: mechanical_tests_log-${{ matrix.mechanical-version }}.txt - retention-days: 7 - - embedding-tests: - name: Embedding testing and coverage - runs-on: ubuntu-latest - timeout-minutes: 30 - needs: [revn-variations, test-container-info, container-stability-check, smoke-tests] - container: - image: ${{ needs.revn-variations.outputs.test_container }} - options: --entrypoint /bin/bash - strategy: - fail-fast: false - matrix: - python-version: ['3.10', '3.11', '3.12', '3.13'] - - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up Python - shell: bash - run: | - apt update - apt install lsb-release xvfb git curl make -y - curl -LsSf https://astral.sh/uv/install.sh | sh - export PATH="$HOME/.local/bin:$PATH" - uv python install python${{ env.MAIN_PYTHON_VERSION }} - uv venv /env - - name: "Install packages for testing" - run: | - . /env/bin/activate - uv pip install --upgrade pip - uv pip install -e .[tests] - - - name: Unit Testing and coverage - env: - ANSYS_WORKBENCH_LOGGING_CONSOLE: 0 - ANSYS_WORKBENCH_LOGGING: 0 - ANSYS_WORKBENCH_LOGGING_FILTER_LEVEL: 2 - NUM_CORES: 1 - PYTHONUNBUFFERED: 1 - run: | - . /env/bin/activate - if [ "${{ needs.container-stability-check.outputs.container_stable_exit }}" = "true" ]; then - xvfb-run mechanical-env pytest -m embedding -s --junitxml test_results${{ matrix.python-version }}.xml - else - xvfb-run mechanical-env pytest -m embedding -s --junitxml test_results${{ matrix.python-version }}.xml || true - fi - - - name: Upload coverage results - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: env.MAIN_PYTHON_VERSION == matrix.python-version - with: - include-hidden-files: true - name: coverage-tests-embedding - path: .cov - retention-days: 7 - - - name: Upload coverage results (as .coverage) - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: env.MAIN_PYTHON_VERSION == matrix.python-version - with: - include-hidden-files: true - name: coverage-file-tests-embedding - path: .coverage - retention-days: 7 - - - name: Publish Test Report - uses: mikepenz/action-junit-report@5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4 # v6.0.0 - if: always() - with: - report_paths: '**/test_results*.xml' - check_name: Test Report ${{ matrix.python-version }} - detailed_summary: true - include_passed: true - fail_on_failure: true - - embedding-scripts-tests: - name: Embedding scripts testing and coverage - runs-on: ubuntu-latest - timeout-minutes: 30 - needs: [smoke-tests, revn-variations, test-container-info] - container: - image: ${{ needs.revn-variations.outputs.test_container }} - options: --entrypoint /bin/bash - strategy: - fail-fast: false - matrix: - python-version: ['3.10', '3.11', '3.12', '3.13'] - - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up Python - shell: bash - run: | - apt update - apt install lsb-release xvfb git curl make -y - curl -LsSf https://astral.sh/uv/install.sh | sh - export PATH="$HOME/.local/bin:$PATH" - uv python install python${{ env.MAIN_PYTHON_VERSION }} - uv venv /env - - name: "Install packages for testing" - run: | - . /env/bin/activate - uv pip install --upgrade pip - uv pip install -e .[tests] - - - name: Embedding scripts unit testing and coverage - env: - ANSYS_WORKBENCH_LOGGING_CONSOLE: 0 - ANSYS_WORKBENCH_LOGGING: 0 - ANSYS_WORKBENCH_LOGGING_FILTER_LEVEL: 2 - NUM_CORES: 1 - PYTHONUNBUFFERED: 1 - run: | - . /env/bin/activate - mechanical-env pytest -m embedding_scripts -s --junitxml test_results_embedding_scripts${{ matrix.python-version }}.xml - pytest -m cli -s --junitxml test_results_cli_scripts${{ matrix.python-version }}.xml - - - name: Upload coverage results - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: env.MAIN_PYTHON_VERSION == matrix.python-version - with: - include-hidden-files: true - name: coverage-tests-embedding-scripts - path: .cov - retention-days: 7 - - - name: Upload coverage results (as .coverage) - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: env.MAIN_PYTHON_VERSION == matrix.python-version - with: - include-hidden-files: true - name: coverage-file-tests-embedding-scripts - path: .coverage - retention-days: 7 - - - name: Publish Test Report - uses: mikepenz/action-junit-report@5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4 # v6.0.0 - if: always() - with: - report_paths: '**/test_results*.xml' - check_name: Test Report ${{ matrix.python-version }} - detailed_summary: true - include_passed: true - fail_on_failure: true - - launch-tests: - name: Launch testing and coverage - runs-on: public-ubuntu-latest-8-cores - timeout-minutes: 30 - container: - image: ${{ needs.revn-variations.outputs.test_container }} - options: --entrypoint /bin/bash - needs: [ style, revn-variations, container-stability-check, test-container-info] - strategy: - fail-fast: false - matrix: - python-version: ['3.10', '3.11', '3.12', '3.13'] - - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up Python - shell: bash - run: | - apt update - apt install lsb-release xvfb git curl make -y - curl -LsSf https://astral.sh/uv/install.sh | sh - export PATH="$HOME/.local/bin:$PATH" - uv python install python${{ env.MAIN_PYTHON_VERSION }} - uv venv /env - - name: "Install packages for testing" - run: | - . /env/bin/activate - uv pip install --upgrade pip - uv pip install -e .[tests] - - - name: Set environment variable - run: echo "ANSYSCL${{ needs.revn-variations.outputs.test_revn }}_DIR=/install/ansys_inc/v${{ needs.revn-variations.outputs.test_revn }}/licensingclient" >> $GITHUB_ENV - - - name: Unit Testing and coverage - env: - ANSYS_WORKBENCH_LOGGING_CONSOLE: 0 - run: | - unset PYMECHANICAL_PORT - unset PYMECHANICAL_START_INSTANCE - . /env/bin/activate - if [ "${{ needs.container-stability-check.outputs.container_stable_exit }}" = "true" ]; then - pytest -m remote_session_launch -s --junitxml launch_test_results${{ matrix.python-version }}.xml - else - pytest -m remote_session_launch -s --junitxml launch_test_results${{ matrix.python-version }}.xml || true - fi - - - name: Publish Launch Test Report - uses: mikepenz/action-junit-report@5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4 # v6.0.0 - if: always() - with: - report_paths: '**/launch_test_results*.xml' - check_name: Launch Test Report ${{ matrix.python-version }} - detailed_summary: true - include_passed: true - fail_on_failure: true - - - name: Upload coverage results - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: env.MAIN_PYTHON_VERSION == matrix.python-version - with: - include-hidden-files: true - name: coverage-tests-remote-session-launch - path: .cov - retention-days: 7 - - - name: Upload coverage results (as .coverage) - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: env.MAIN_PYTHON_VERSION == matrix.python-version - with: - include-hidden-files: true - name: coverage-file-tests-remote-session-launch - path: .coverage - retention-days: 7 + # test-container-info: + # name: Get SHA of test container + # runs-on: public-ubuntu-latest-8-cores + # needs: [revn-variations] + # outputs: + # sha: ${{ steps.get_sha.outputs.sha }} + # strategy: + # matrix: + # test_container: ['${{ needs.revn-variations.outputs.test_container }}'] + # steps: + # - name: Login in Github Container registry + # uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + # with: + # registry: ghcr.io + # username: ${{ github.actor }} + # password: ${{ secrets.GITHUB_TOKEN }} + + # - name: Pull, launch, and validate Mechanical service + # id: get_sha + # env: + # MECHANICAL_IMAGE: ${{ matrix.test_container }} + # run: | + # # Install jq for parsing JSON + # pip install jq + + # # Get docker info + # image_info=$(docker manifest inspect -v ${{ env.MECHANICAL_IMAGE }}) # --format ".Descriptor.digest" + + # # Get digest SHA + # digest=$(echo "$image_info" | jq -r '.Descriptor.digest') + + # # Remove the "sha256:" prefix to get only the SHA + # sha="${digest#*:}" + # echo "SHA of image ${{ env.MECHANICAL_IMAGE }} is $sha" + # echo "sha=$sha" >> $GITHUB_OUTPUT + + # config-matrix: + # runs-on: ubuntu-latest + # needs: [revn-variations] + # outputs: + # matrix: ${{ steps.set-matrix.outputs.matrix }} + # steps: + # - id: set-matrix + # run: | + # # if a tag(release) is pushed, test all versions + # if ${{ github.event_name == 'push' }} && ${{ contains(github.ref, 'refs/tags') }}; then + # echo "matrix={\"mechanical-version\":['24.1.0', '24.2.0', '25.1.0', '25.2.0'],\"experimental\":[false]}" >> $GITHUB_OUTPUT + # else + # echo "matrix={\"mechanical-version\":['${{ needs.revn-variations.outputs.test_docker_image_version }}'],\"experimental\":[false]}" >> $GITHUB_OUTPUT + # fi + + # container-stability-check: + # runs-on: ubuntu-latest + # needs: [revn-variations] + # outputs: + # container_stable_exit: ${{ steps.check_stability.outputs.container_stable_exit }} + # steps: + # - id: check_stability + # run: | + # sudo apt update + # sudo apt install bc -y + # container_version=$(echo "${{ needs.revn-variations.outputs.test_docker_image_version }}" | grep -o -E '[0-9]+(\.[0-9]+)?' | head -n 1) + # if (( $(echo "$container_version > 24.2" | bc -l) )); then + # echo "container_stable_exit=true" >> $GITHUB_OUTPUT + # else + # echo "container_stable_exit=false" >> $GITHUB_OUTPUT + # fi + + # remote-connect: + # name: Remote connect testing and coverage - Mechanical ${{ matrix.mechanical-version }} + # runs-on: public-ubuntu-latest-8-cores + # needs: [style, revn-variations, config-matrix] + # continue-on-error: ${{ matrix.experimental }} + # strategy: + # fail-fast: false + # matrix: ${{ fromJSON(needs.config-matrix.outputs.matrix) }} + # steps: + # - name: Login in Github Container registry + # uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + # with: + # registry: ghcr.io + # username: ${{ github.actor }} + # password: ${{ secrets.GITHUB_TOKEN }} + + # - name: Pull, launch, and validate Mechanical service + # env: + # MECHANICAL_IMAGE: ${{ env.DOCKER_PACKAGE }}:${{ matrix.mechanical-version }} + # # ANSYS_WORKBENCH_LOGGING_CONSOLE: 0 + # # ANSYS_WORKBENCH_LOGGING_DIRECTORY: /log_file # workbench.log file + # ANSYS_WORKBENCH_LOGGING_AUTO_FLUSH: 0 # turn off autoflush for faster performance + # run: | + # docker pull ${{ env.MECHANICAL_IMAGE }} + + # echo "Run docker in detached mode" + # docker run -d --name ${{ env.DOCKER_MECH_CONTAINER_NAME }} -e ANSYSLMD_LICENSE_FILE=1055@${{ env.LICENSE_SERVER }} -p ${{ env.PYMECHANICAL_PORT }}:10000 ${{ env.MECHANICAL_IMAGE }} + + # # Wait for Mechanical to initialize with intelligent polling + # max_wait=300 # Maximum wait time in seconds + # check_interval=10 # Check every 10 seconds + # elapsed=0 + + # echo "Waiting for Mechanical to initialize..." + # while [ $elapsed -lt $max_wait ]; do + # docker logs ${{ env.DOCKER_MECH_CONTAINER_NAME }} > log.txt + # if grep -q 'WB Initialize Done' log.txt 2>/dev/null; then + # echo "Mechanical initialized successfully after ${elapsed} seconds" + # break + # fi + # echo "Waiting for initialization... (${elapsed}/${max_wait}s)" + # sleep $check_interval + # elapsed=$((elapsed + check_interval)) + # done + + # # Final check + # docker logs ${{ env.DOCKER_MECH_CONTAINER_NAME }} > log.txt + # if ! grep -q 'WB Initialize Done' log.txt 2>/dev/null; then + # echo "ERROR: Mechanical failed to initialize within ${max_wait} seconds" + # echo "=== Last 50 lines of log.txt ===" + # tail -n 50 log.txt || echo "No log file found" + # exit 1 + # fi + + # - name: Display info + # if: github.event_name == 'schedule' + # id: capture_info + # run: | + # IMAGE_NAME=${{ env.DOCKER_PACKAGE }}:${{ matrix.mechanical-version }} + # BUILD_DATE=$(docker run --rm --entrypoint head $IMAGE_NAME -n 1 /install/ansys_inc/v${{ needs.revn-variations.outputs.test_revn }}/aisol/CommonFiles/builddate.txt) + # PUSHED_AT=$(docker inspect --format='{{.Created}}' $IMAGE_NAME) + # echo "docker_info=$IMAGE_NAME was pushed at: $PUSHED_AT" >> $GITHUB_OUTPUT + # echo "::group::Docker Info" + # echo "docker_info=$PUSHED_AT" >> $GITHUB_OUTPUT + # echo "build_info=$BUILD_DATE" >> $GITHUB_OUTPUT + # echo "$IMAGE_NAME pushed at $PUSHED_AT" + # echo "Build date : $BUILD_DATE" + # echo "::endgroup::" + + # - name: Testing + # uses: ansys/actions/tests-pytest@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # python-version: ${{ env.MAIN_PYTHON_VERSION }} + # pytest-markers: '-m remote_session_connect' + # pytest-extra-args: '-s --junitxml remote_results${{ env.MAIN_PYTHON_VERSION}}.xml' + + # - name: Publish Test Report + # uses: mikepenz/action-junit-report@5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4 # v6.0.0 + # if: always() + # with: + # report_paths: '**/remote_results*.xml' + # check_name: Remote Connect Test Report ${{ env.MAIN_PYTHON_VERSION}} + # detailed_summary: true + # include_passed: true + # fail_on_failure: true + + # - name: Upload coverage results + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # if: matrix.mechanical-version == needs.revn-variations.outputs.test_docker_image_version + # with: + # include-hidden-files: true + # name: coverage-tests + # path: .cov + # retention-days: 7 + + # - name: Upload coverage results (as .coverage) + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # if: matrix.mechanical-version == needs.revn-variations.outputs.test_docker_image_version + # with: + # include-hidden-files: true + # name: coverage-file-tests + # path: .coverage + # retention-days: 7 + + # - name: Get Mechanical container logs + # if: always() + # run: | + # docker logs ${{ env.DOCKER_MECH_CONTAINER_NAME }} > mechanical_tests_log-${{ matrix.mechanical-version }}.txt 2>&1 + # echo CONTAINER LOGS OUTPUT + # cat mechanical_tests_log-${{ matrix.mechanical-version }}.txt + # echo CPU info + # lscpu + + # - name: Upload container logs + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # with: + # name: mechanical_tests_log-${{ matrix.mechanical-version }} + # path: mechanical_tests_log-${{ matrix.mechanical-version }}.txt + # retention-days: 7 + + # embedding-tests: + # name: Embedding testing and coverage + # runs-on: ubuntu-latest + # timeout-minutes: 30 + # needs: [revn-variations, test-container-info, container-stability-check, smoke-tests] + # container: + # image: ${{ needs.revn-variations.outputs.test_container }} + # options: --entrypoint /bin/bash + # strategy: + # fail-fast: false + # matrix: + # python-version: ['3.10', '3.11', '3.12', '3.13'] + + # steps: + # - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + # - name: Set up Python + # shell: bash + # run: | + # apt update + # apt install lsb-release xvfb git curl make -y + # curl -LsSf https://astral.sh/uv/install.sh | sh + # export PATH="$HOME/.local/bin:$PATH" + # uv python install python${{ env.MAIN_PYTHON_VERSION }} + # uv venv /env + # - name: "Install packages for testing" + # run: | + # . /env/bin/activate + # uv pip install --upgrade pip + # uv pip install -e .[tests] + + # - name: Unit Testing and coverage + # env: + # ANSYS_WORKBENCH_LOGGING_CONSOLE: 0 + # ANSYS_WORKBENCH_LOGGING: 0 + # ANSYS_WORKBENCH_LOGGING_FILTER_LEVEL: 2 + # NUM_CORES: 1 + # PYTHONUNBUFFERED: 1 + # run: | + # . /env/bin/activate + # if [ "${{ needs.container-stability-check.outputs.container_stable_exit }}" = "true" ]; then + # xvfb-run mechanical-env pytest -m embedding -s --junitxml test_results${{ matrix.python-version }}.xml + # else + # xvfb-run mechanical-env pytest -m embedding -s --junitxml test_results${{ matrix.python-version }}.xml || true + # fi + + # - name: Upload coverage results + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # if: env.MAIN_PYTHON_VERSION == matrix.python-version + # with: + # include-hidden-files: true + # name: coverage-tests-embedding + # path: .cov + # retention-days: 7 + + # - name: Upload coverage results (as .coverage) + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # if: env.MAIN_PYTHON_VERSION == matrix.python-version + # with: + # include-hidden-files: true + # name: coverage-file-tests-embedding + # path: .coverage + # retention-days: 7 + + # - name: Publish Test Report + # uses: mikepenz/action-junit-report@5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4 # v6.0.0 + # if: always() + # with: + # report_paths: '**/test_results*.xml' + # check_name: Test Report ${{ matrix.python-version }} + # detailed_summary: true + # include_passed: true + # fail_on_failure: true + + # embedding-scripts-tests: + # name: Embedding scripts testing and coverage + # runs-on: ubuntu-latest + # timeout-minutes: 30 + # needs: [smoke-tests, revn-variations, test-container-info] + # container: + # image: ${{ needs.revn-variations.outputs.test_container }} + # options: --entrypoint /bin/bash + # strategy: + # fail-fast: false + # matrix: + # python-version: ['3.10', '3.11', '3.12', '3.13'] + + # steps: + # - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + # - name: Set up Python + # shell: bash + # run: | + # apt update + # apt install lsb-release xvfb git curl make -y + # curl -LsSf https://astral.sh/uv/install.sh | sh + # export PATH="$HOME/.local/bin:$PATH" + # uv python install python${{ env.MAIN_PYTHON_VERSION }} + # uv venv /env + # - name: "Install packages for testing" + # run: | + # . /env/bin/activate + # uv pip install --upgrade pip + # uv pip install -e .[tests] + + # - name: Embedding scripts unit testing and coverage + # env: + # ANSYS_WORKBENCH_LOGGING_CONSOLE: 0 + # ANSYS_WORKBENCH_LOGGING: 0 + # ANSYS_WORKBENCH_LOGGING_FILTER_LEVEL: 2 + # NUM_CORES: 1 + # PYTHONUNBUFFERED: 1 + # run: | + # . /env/bin/activate + # mechanical-env pytest -m embedding_scripts -s --junitxml test_results_embedding_scripts${{ matrix.python-version }}.xml + # pytest -m cli -s --junitxml test_results_cli_scripts${{ matrix.python-version }}.xml + + # - name: Upload coverage results + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # if: env.MAIN_PYTHON_VERSION == matrix.python-version + # with: + # include-hidden-files: true + # name: coverage-tests-embedding-scripts + # path: .cov + # retention-days: 7 + + # - name: Upload coverage results (as .coverage) + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # if: env.MAIN_PYTHON_VERSION == matrix.python-version + # with: + # include-hidden-files: true + # name: coverage-file-tests-embedding-scripts + # path: .coverage + # retention-days: 7 + + # - name: Publish Test Report + # uses: mikepenz/action-junit-report@5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4 # v6.0.0 + # if: always() + # with: + # report_paths: '**/test_results*.xml' + # check_name: Test Report ${{ matrix.python-version }} + # detailed_summary: true + # include_passed: true + # fail_on_failure: true + + # launch-tests: + # name: Launch testing and coverage + # runs-on: public-ubuntu-latest-8-cores + # timeout-minutes: 30 + # container: + # image: ${{ needs.revn-variations.outputs.test_container }} + # options: --entrypoint /bin/bash + # needs: [ style, revn-variations, container-stability-check, test-container-info] + # strategy: + # fail-fast: false + # matrix: + # python-version: ['3.10', '3.11', '3.12', '3.13'] + + # steps: + # - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + # - name: Set up Python + # shell: bash + # run: | + # apt update + # apt install lsb-release xvfb git curl make -y + # curl -LsSf https://astral.sh/uv/install.sh | sh + # export PATH="$HOME/.local/bin:$PATH" + # uv python install python${{ env.MAIN_PYTHON_VERSION }} + # uv venv /env + # - name: "Install packages for testing" + # run: | + # . /env/bin/activate + # uv pip install --upgrade pip + # uv pip install -e .[tests] + + # - name: Set environment variable + # run: echo "ANSYSCL${{ needs.revn-variations.outputs.test_revn }}_DIR=/install/ansys_inc/v${{ needs.revn-variations.outputs.test_revn }}/licensingclient" >> $GITHUB_ENV + + # - name: Unit Testing and coverage + # env: + # ANSYS_WORKBENCH_LOGGING_CONSOLE: 0 + # run: | + # unset PYMECHANICAL_PORT + # unset PYMECHANICAL_START_INSTANCE + # . /env/bin/activate + # if [ "${{ needs.container-stability-check.outputs.container_stable_exit }}" = "true" ]; then + # pytest -m remote_session_launch -s --junitxml launch_test_results${{ matrix.python-version }}.xml + # else + # pytest -m remote_session_launch -s --junitxml launch_test_results${{ matrix.python-version }}.xml || true + # fi + + # - name: Publish Launch Test Report + # uses: mikepenz/action-junit-report@5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4 # v6.0.0 + # if: always() + # with: + # report_paths: '**/launch_test_results*.xml' + # check_name: Launch Test Report ${{ matrix.python-version }} + # detailed_summary: true + # include_passed: true + # fail_on_failure: true + + # - name: Upload coverage results + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # if: env.MAIN_PYTHON_VERSION == matrix.python-version + # with: + # include-hidden-files: true + # name: coverage-tests-remote-session-launch + # path: .cov + # retention-days: 7 + + # - name: Upload coverage results (as .coverage) + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # if: env.MAIN_PYTHON_VERSION == matrix.python-version + # with: + # include-hidden-files: true + # name: coverage-file-tests-remote-session-launch + # path: .coverage + # retention-days: 7 doc-build: name: Documentation @@ -572,8 +572,8 @@ jobs: container: image: ${{ needs.revn-variations.outputs.test_container }} options: --entrypoint /bin/bash - needs: [style, doc-style, revn-variations, container-stability-check, test-container-info] - + needs: [revn-variations] + #needs: [style, doc-style, revn-variations, container-stability-check, test-container-info] steps: - name: Install Git and checkout project @@ -658,249 +658,249 @@ jobs: path: doc/_build/html retention-days: 7 - doc-deploy-pr: - name: "Deploy PR documentation" - runs-on: ubuntu-latest - needs: [doc-build] - if: always() && (needs.doc-build.result == 'success' || needs.doc-build.result == 'skipped') - steps: - - uses: ansys/actions/doc-deploy-pr@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - cname: ${{ env.DOCUMENTATION_CNAME }} - token: ${{ secrets.GITHUB_TOKEN }} - bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} - bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} - maximum-pr-doc-deployments: 10 - - coverage: - name: Merging coverage - needs: [remote-connect, embedding-tests, embedding-scripts-tests, launch-tests] - # needs: [remote-connect, embedding-tests, embedding-scripts-tests, embedding-rpc-tests, launch-tests] - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Install coverage - run: | - rm -rf ./env - python -m pip install -U pip - pip install coverage - pip install -e . - - - name: Create common coverage directory - run: mkdir cov-dir - - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 - with: - name: coverage-file-tests-embedding - path: cov-dir/embedding - - # - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 - # with: - # name: coverage-file-tests-embedding-rpc - # path: cov-dir/embedding-rpc - - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 - with: - name: coverage-file-tests-embedding-scripts - path: cov-dir/embedding-scripts - - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 - with: - name: coverage-file-tests-remote-session-launch - path: cov-dir/launch - - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 - with: - name: coverage-file-tests - path: cov-dir/normal - - - name: Display structure of downloaded files - run: ls -Ra - - - name: Move files to common location - run: | - mv cov-dir/embedding/.coverage .coverage.Embedding - # mv cov-dir/embedding-rpc/.coverage .coverage.EmbeddingRPC - mv cov-dir/embedding-scripts/.coverage .coverage.EmbeddingScripts - mv cov-dir/launch/.coverage .coverage.Launch - mv cov-dir/normal/.coverage .coverage.Normal - rm -rf cov-dir - - - name: Generate .coveragerc file - run: | - cat > .coveragerc << 'EOF' - - # .coveragerc to control coverage.py - [run] - relative_files = True - - [paths] - source = - src/ansys/mechanical - /opt/hostedtoolcache/**/ansys/mechanical - /usr/local/lib/**/ansys/mechanical - .venv/lib/**/ansys/mechanical - /env/lib/**/ansys/mechanical - EOF - - - name: Run coverage merge and show results - run: | - coverage combine --keep --debug=pathmap --rcfile=.coveragerc - coverage report - coverage html -d .coverage-combined/html - coverage xml -o .coverage-combined/xml - - - name: Upload combined coverage results - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - include-hidden-files: true - name: combined-coverage-results - path: .coverage-combined - retention-days: 7 - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - with: - files: .coverage-combined/xml - - - name: Upload coverage to Codacy - uses: codacy/codacy-coverage-reporter-action@89d6c85cfafaec52c72b6c5e8b2878d33104c699 # v1.3.0 - with: - project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} - coverage-reports: '.coverage-combined/xml' - - package: - name: Package library - needs: [smoke-tests, remote-connect, embedding-tests, embedding-scripts-tests, doc-build] - runs-on: ubuntu-latest - permissions: - attestations: write - contents: read - id-token: write - steps: - - name: Build library source and wheel artifacts - uses: ansys/actions/build-library@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - library-name: ${{ env.PACKAGE_NAME }} - python-version: ${{ env.MAIN_PYTHON_VERSION }} - attest-provenance: true - - release: - name: Release project to GitHub - if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - needs: [package, update-changelog] - runs-on: ubuntu-latest - permissions: - id-token: write - contents: write - steps: - - name: Release to GitHub - uses: ansys/actions/release-github@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - token: ${{ secrets.GITHUB_TOKEN }} - library-name: ${{ env.PACKAGE_NAME }} - only-code: true - - release-pypi: - name: Release project to PyPI - if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - needs: [package, update-changelog] - runs-on: ubuntu-latest - permissions: - id-token: write - contents: write - steps: - - name: "Download the library artifacts from build-library step" - uses: actions/download-artifact@de96f4613b77ec03b5cf633e7c350c32bd3c5660 # v4.3.0 - with: - name: ${{ env.PACKAGE_NAME }}-artifacts - path: ${{ env.PACKAGE_NAME }}-artifacts - - - name: "Upload artifacts to PyPI using trusted publisher" - uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 - with: - repository-url: "https://upload.pypi.org/legacy/" - print-hash: true - packages-dir: ${{ env.PACKAGE_NAME }}-artifacts - skip-existing: false - - upload_dev_docs: - name: Upload dev documentation - if: github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - needs: [package] - steps: - - name: Deploy the latest documentation - uses: ansys/actions/doc-deploy-dev@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - cname: ${{ env.DOCUMENTATION_CNAME }} - token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} - bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} - bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} - - upload_docs_release: - name: Upload release documentation - if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - runs-on: ubuntu-latest - needs: [release] - steps: - - name: Deploy the stable documentation - uses: ansys/actions/doc-deploy-stable@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 - with: - cname: ${{ env.DOCUMENTATION_CNAME }} - token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} - bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} - bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} - - get-date: - name: Get date - runs-on: ubuntu-latest - outputs: - date: ${{ steps.date.outputs.date }} - steps: - - name: Get current date - id: date - run: | - echo "date=$(date --iso-8601)" >> $GITHUB_OUTPUT - - notify-on-failure: - name: Notify on failure - needs: [get-date, embedding-tests, embedding-scripts-tests, launch-tests, remote-connect, doc-build] - if: github.event_name == 'schedule' && (failure() || cancelled()) - runs-on: ubuntu-latest - steps: - - name: Microsoft Teams Notification - uses: skitionek/notify-microsoft-teams@11e40c38c3a629ae65a985b582eca4897b01e79e # v1.0.9 - with: - webhook_url: ${{ secrets.MSTEAMS_WEBHOOK }} - # Message to send to Teams as a webhook notification in JSON Payload format - raw: >- - { - "type": "message", - "attachments": [ - { - "contentType": "application/vnd.microsoft.card.adaptive", - "content": { - "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", - "type": "AdaptiveCard", - "version": "1.0", - "body": [ - { - "type": "TextBlock", - "text": "**PyMechanical Nightly Run Failed on ${{ needs.get-date.outputs.date }}**\n\n[View details in GitHub Actions](https://github.com/ansys/pymechanical/actions/runs/${{ github.run_id }})", - "wrap": true - } - ] - } - } - ] - } \ No newline at end of file + # doc-deploy-pr: + # name: "Deploy PR documentation" + # runs-on: ubuntu-latest + # needs: [doc-build] + # if: always() && (needs.doc-build.result == 'success' || needs.doc-build.result == 'skipped') + # steps: + # - uses: ansys/actions/doc-deploy-pr@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # cname: ${{ env.DOCUMENTATION_CNAME }} + # token: ${{ secrets.GITHUB_TOKEN }} + # bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} + # bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} + # maximum-pr-doc-deployments: 10 + + # coverage: + # name: Merging coverage + # needs: [remote-connect, embedding-tests, embedding-scripts-tests, launch-tests] + # # needs: [remote-connect, embedding-tests, embedding-scripts-tests, embedding-rpc-tests, launch-tests] + # runs-on: ubuntu-latest + # steps: + # - name: Checkout repository + # uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + # - name: Set up Python + # uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + # with: + # python-version: ${{ env.MAIN_PYTHON_VERSION }} + + # - name: Install coverage + # run: | + # rm -rf ./env + # python -m pip install -U pip + # pip install coverage + # pip install -e . + + # - name: Create common coverage directory + # run: mkdir cov-dir + + # - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + # with: + # name: coverage-file-tests-embedding + # path: cov-dir/embedding + + # # - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + # # with: + # # name: coverage-file-tests-embedding-rpc + # # path: cov-dir/embedding-rpc + + # - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + # with: + # name: coverage-file-tests-embedding-scripts + # path: cov-dir/embedding-scripts + + # - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + # with: + # name: coverage-file-tests-remote-session-launch + # path: cov-dir/launch + + # - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + # with: + # name: coverage-file-tests + # path: cov-dir/normal + + # - name: Display structure of downloaded files + # run: ls -Ra + + # - name: Move files to common location + # run: | + # mv cov-dir/embedding/.coverage .coverage.Embedding + # # mv cov-dir/embedding-rpc/.coverage .coverage.EmbeddingRPC + # mv cov-dir/embedding-scripts/.coverage .coverage.EmbeddingScripts + # mv cov-dir/launch/.coverage .coverage.Launch + # mv cov-dir/normal/.coverage .coverage.Normal + # rm -rf cov-dir + + # - name: Generate .coveragerc file + # run: | + # cat > .coveragerc << 'EOF' + + # # .coveragerc to control coverage.py + # [run] + # relative_files = True + + # [paths] + # source = + # src/ansys/mechanical + # /opt/hostedtoolcache/**/ansys/mechanical + # /usr/local/lib/**/ansys/mechanical + # .venv/lib/**/ansys/mechanical + # /env/lib/**/ansys/mechanical + # EOF + + # - name: Run coverage merge and show results + # run: | + # coverage combine --keep --debug=pathmap --rcfile=.coveragerc + # coverage report + # coverage html -d .coverage-combined/html + # coverage xml -o .coverage-combined/xml + + # - name: Upload combined coverage results + # uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + # with: + # include-hidden-files: true + # name: combined-coverage-results + # path: .coverage-combined + # retention-days: 7 + + # - name: Upload coverage to Codecov + # uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + # env: + # CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + # with: + # files: .coverage-combined/xml + + # - name: Upload coverage to Codacy + # uses: codacy/codacy-coverage-reporter-action@89d6c85cfafaec52c72b6c5e8b2878d33104c699 # v1.3.0 + # with: + # project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} + # coverage-reports: '.coverage-combined/xml' + + # package: + # name: Package library + # needs: [smoke-tests, remote-connect, embedding-tests, embedding-scripts-tests, doc-build] + # runs-on: ubuntu-latest + # permissions: + # attestations: write + # contents: read + # id-token: write + # steps: + # - name: Build library source and wheel artifacts + # uses: ansys/actions/build-library@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # library-name: ${{ env.PACKAGE_NAME }} + # python-version: ${{ env.MAIN_PYTHON_VERSION }} + # attest-provenance: true + + # release: + # name: Release project to GitHub + # if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + # needs: [package, update-changelog] + # runs-on: ubuntu-latest + # permissions: + # id-token: write + # contents: write + # steps: + # - name: Release to GitHub + # uses: ansys/actions/release-github@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # library-name: ${{ env.PACKAGE_NAME }} + # only-code: true + + # release-pypi: + # name: Release project to PyPI + # if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + # needs: [package, update-changelog] + # runs-on: ubuntu-latest + # permissions: + # id-token: write + # contents: write + # steps: + # - name: "Download the library artifacts from build-library step" + # uses: actions/download-artifact@de96f4613b77ec03b5cf633e7c350c32bd3c5660 # v4.3.0 + # with: + # name: ${{ env.PACKAGE_NAME }}-artifacts + # path: ${{ env.PACKAGE_NAME }}-artifacts + + # - name: "Upload artifacts to PyPI using trusted publisher" + # uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + # with: + # repository-url: "https://upload.pypi.org/legacy/" + # print-hash: true + # packages-dir: ${{ env.PACKAGE_NAME }}-artifacts + # skip-existing: false + + # upload_dev_docs: + # name: Upload dev documentation + # if: github.ref == 'refs/heads/main' + # runs-on: ubuntu-latest + # needs: [package] + # steps: + # - name: Deploy the latest documentation + # uses: ansys/actions/doc-deploy-dev@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # cname: ${{ env.DOCUMENTATION_CNAME }} + # token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} + # bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} + # bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} + + # upload_docs_release: + # name: Upload release documentation + # if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + # runs-on: ubuntu-latest + # needs: [release] + # steps: + # - name: Deploy the stable documentation + # uses: ansys/actions/doc-deploy-stable@33399106dc8b62d83c8aad1fb2c333c8055df180 # v10.0.20 + # with: + # cname: ${{ env.DOCUMENTATION_CNAME }} + # token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} + # bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} + # bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} + + # get-date: + # name: Get date + # runs-on: ubuntu-latest + # outputs: + # date: ${{ steps.date.outputs.date }} + # steps: + # - name: Get current date + # id: date + # run: | + # echo "date=$(date --iso-8601)" >> $GITHUB_OUTPUT + + # notify-on-failure: + # name: Notify on failure + # needs: [get-date, embedding-tests, embedding-scripts-tests, launch-tests, remote-connect, doc-build] + # if: github.event_name == 'schedule' && (failure() || cancelled()) + # runs-on: ubuntu-latest + # steps: + # - name: Microsoft Teams Notification + # uses: skitionek/notify-microsoft-teams@11e40c38c3a629ae65a985b582eca4897b01e79e # v1.0.9 + # with: + # webhook_url: ${{ secrets.MSTEAMS_WEBHOOK }} + # # Message to send to Teams as a webhook notification in JSON Payload format + # raw: >- + # { + # "type": "message", + # "attachments": [ + # { + # "contentType": "application/vnd.microsoft.card.adaptive", + # "content": { + # "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + # "type": "AdaptiveCard", + # "version": "1.0", + # "body": [ + # { + # "type": "TextBlock", + # "text": "**PyMechanical Nightly Run Failed on ${{ needs.get-date.outputs.date }}**\n\n[View details in GitHub Actions](https://github.com/ansys/pymechanical/actions/runs/${{ github.run_id }})", + # "wrap": true + # } + # ] + # } + # } + # ] + # } \ No newline at end of file From 1a05679cb04a0e9e3c11e84aa181ad1c5385b61e Mon Sep 17 00:00:00 2001 From: kmcadams Date: Tue, 28 Oct 2025 13:26:25 -0400 Subject: [PATCH 35/52] add verbose option --- doc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Makefile b/doc/Makefile index d633409e5..7fa80c5b0 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -16,7 +16,7 @@ help: # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) --verbose # customized clean due to examples gallery clean: From b34a0a1cdbc7b1c708c799d675a01617254ac51f Mon Sep 17 00:00:00 2001 From: kmcadams Date: Tue, 28 Oct 2025 14:08:15 -0400 Subject: [PATCH 36/52] test --- examples/00_setup/01_setup.py | 2 +- examples/00_setup/{01_setup2.py => 02_setup.py} | 2 +- examples/00_setup/{01_setup3.py => 03_setup.py} | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename examples/00_setup/{01_setup2.py => 02_setup.py} (99%) rename examples/00_setup/{01_setup3.py => 03_setup.py} (99%) diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index dbea00565..96fc8b29e 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -""".. _ref_setup: +""".. _ref_setup_1: App --- diff --git a/examples/00_setup/01_setup2.py b/examples/00_setup/02_setup.py similarity index 99% rename from examples/00_setup/01_setup2.py rename to examples/00_setup/02_setup.py index dbea00565..e498840df 100644 --- a/examples/00_setup/01_setup2.py +++ b/examples/00_setup/02_setup.py @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -""".. _ref_setup: +""".. _ref_setup_2: App --- diff --git a/examples/00_setup/01_setup3.py b/examples/00_setup/03_setup.py similarity index 99% rename from examples/00_setup/01_setup3.py rename to examples/00_setup/03_setup.py index dbea00565..efff44dac 100644 --- a/examples/00_setup/01_setup3.py +++ b/examples/00_setup/03_setup.py @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -""".. _ref_setup: +""".. _ref_setup_3: App --- From ed0642a5d26b0516e4ed7386ad474a843ff3c08f Mon Sep 17 00:00:00 2001 From: kmcadams Date: Tue, 28 Oct 2025 14:39:57 -0400 Subject: [PATCH 37/52] add geometry example --- examples/00_setup/02_geometry.py | 485 +++++++++++++++++++++++++++++++ examples/00_setup/02_setup.py | 171 ----------- examples/00_setup/03_setup.py | 171 ----------- 3 files changed, 485 insertions(+), 342 deletions(-) create mode 100644 examples/00_setup/02_geometry.py delete mode 100644 examples/00_setup/02_setup.py delete mode 100644 examples/00_setup/03_setup.py diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py new file mode 100644 index 000000000..fd5204787 --- /dev/null +++ b/examples/00_setup/02_geometry.py @@ -0,0 +1,485 @@ +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +""".. _ref_geometry: + +Geometry +-------- + +This section contains a few utility scripts for working with Geometry, +including importing, analyzing, and accessing geometric data, as well +as utilizing it for downstream preprocessing operations in Mechanical +simulations. Coordinate Systems too are covered here. +""" + +import tracemalloc + +# Start tracing memory +tracemalloc.start() + +# %% +# Import Geometry +# ~~~~~~~~~~~~~~~ + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file + +app = App(globals=globals()) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Download the geometry file for the example +geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") +# Alternatively, you can specify a local file path +# or geom_file_path = r"C:\geometry.agdb" + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Import the geometry into the Mechanical model +geometry_import = Model.GeometryImportGroup.AddGeometryImport() +geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic +geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Set preferences for geometry import +geometry_import_preferences.ProcessLines = True +geometry_import_preferences.NamedSelectionKey = "" +geometry_import_preferences.ProcessNamedSelections = True +geometry_import_preferences.ProcessMaterialProperties = True + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Perform the geometry import +geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Plot the imported geometry +app.plot() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Print the tree structure of the Mechanical model +app.print_tree() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + + +# %% +# Get all bodies +# ~~~~~~~~~~~~~~~~~ + +# Retrieve all body objects from the geometry +body_objects = Model.Geometry.GetChildren(DataModelObjectCategory.Body, True) +# Alternatively, use the following method: +# bodies_objects = Model.Geometry.GetChildren(Ansys.ACT.Automation.Mechanical.Body, True) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Extract geometric body wrappers for each body object +bodies = [body.GetGeoBody() for body in body_objects] # GeoBodyWrapper +# or +# import itertools +# nested_list = [x.Bodies for x in ExtAPI.DataModel.GeoData.Assemblies[0].AllParts] +# bodies = list(itertools.chain(*nested_list)) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Access details of the first body object and its geometric properties +bo = body_objects[0] # Access Object Details and RMB options +b = bodies[0] # Access Geometric Properties: 'Area', 'GeoData', 'Centroid', 'Faces', etc. + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Find Body with Largest Volume +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Set the active unit system to Standard NMM +ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Create a list of body names, volumes, and IDs for unsuppressed bodies +body_names_volumes = [] +for body in body_objects: + if body.Suppressed == 0 and body.Volume: + body_names_volumes.append((body.Name, body.Volume, body.GetGeoBody().Id)) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Sort the list and retrieve the body with the largest volume +sorted_name_vol = sorted(body_names_volumes) +bodyname, volu, bodyid = sorted_name_vol.pop() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Print details of the largest body +print(f"Unit System is: {ExtAPI.Application.ActiveUnitSystem}") +print(f"Name of the Largest Body: '{bodyname}'") +print(f"Its Volume: {round(volu.Value, 2)} {volu.Unit}") +print(f"Its id: {bodyid}") + +# %% +# Find Body by its ID +# ~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve a body object using its ID +b2 = DataModel.GeoData.GeoEntityById(bodyid) +print(f"Body Name: {b2.Name}, Body Id: {b2.Id}") + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Find the Part that the body belongs to +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve the name of a body and the part it belongs to using its ID +body_name = DataModel.GeoData.GeoEntityById(59).Name +part_name = DataModel.GeoData.GeoEntityById(59).Part.Name +print(f"The Body named '{body_name}' belongs to the part named '{part_name}'") + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Find Body by its ID AND print its Faces, Centroid, etc. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve a body object and its faces, centroids, etc. +body2 = DataModel.GeoData.GeoEntityById(bodyid) + +# Get face IDs and centroids for each face +face_ids = [face.Id for face in body2.Faces] +centroids_of_each_face = [DataModel.GeoData.GeoEntityById(face_id).Centroid for face_id in face_ids] + +# Print face IDs and their centroids +for face_id, centroid in zip(face_ids, centroids_of_each_face): + print(face_id, list(centroid)) + +# %% +# Get all Vertices +# ~~~~~~~~~~~~~~~~~~~ + +# Retrieve all vertex IDs from the geometry +vertices = [] +geo = DataModel.GeoData +for asm in geo.Assemblies: + for part in asm.Parts: + for body in part.Bodies: + for i in range(0, body.Vertices.Count): + vertices.append(body.Vertices[i].Id) +print(vertices) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Get all edges of a given length +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all edges with a specified length +ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM +use_length = 0.100 + +geo = DataModel.GeoData +edgelist = [] + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Iterate through assemblies, parts, and bodies to find edges of the given length +for asm in geo.Assemblies: + for part in asm.Parts: + for body in part.Bodies: + for edge in body.Edges: + if abs(edge.Length - use_length) <= use_length * 0.01: + edgelist.append(edge.Id) +print(edgelist) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Get all circular edges of a given radius +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all circular edges with a specified radius +import math + +radius = 0.018 # Target radius +circumference = 2 * math.pi * radius # Calculate circumference + +geo = DataModel.GeoData +circlelist = [] + +# Iterate through assemblies, parts, and bodies to find circular edges +for asm in geo.Assemblies: + for part in asm.Parts: + for body in part.Bodies: + for edge in body.Edges: + if ( + abs(edge.Length - circumference) <= circumference * 0.01 + and str(edge.CurveType) == "GeoCurveCircle" + ): + circlelist.append(edge.Id) +print(circlelist) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Get Radius of a selected edge +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve the radius of a specific edge if it is circular +my_edge = DataModel.GeoData.GeoEntityById(27) +my_edge_radius = my_edge.Radius if str(my_edge.CurveType) == "GeoCurveCircle" else 0.0 +print(my_edge_radius) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Create a Named Selection from a list of body Ids +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a named selection for a list of body IDs +mylist = [bodyid] + +selection_manager = ExtAPI.SelectionManager +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection.Ids = mylist +selection_manager.NewSelection(selection) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +ns2 = Model.AddNamedSelection() +ns2.Name = "bodies2" +ns2.Location = selection + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Find a Named Selection with a prefix +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve a named selection whose name starts with a specific prefix +NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) +my_nsel = [i for i in NSall if i.Name.startswith("b")][0] +print(my_nsel.Name) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Create a Named Selection of all bodies with a cylindrical face +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +geo = DataModel.GeoData +cyl_body_ids = [] + +for asm in geo.Assemblies: + for part in asm.Parts: + for body in part.Bodies: + countcyl = 0 + for face in body.Faces: + if ( + face.SurfaceType + == Ansys.ACT.Interfaces.Geometry.GeoSurfaceTypeEnum.GeoSurfaceCylinder + ): + countcyl = countcyl + 1 + if countcyl != 0: + cyl_body_ids.append(body.Id) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +selection_manager = ExtAPI.SelectionManager +selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) +selection.Ids = cyl_body_ids + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +ns2 = Model.AddNamedSelection() +ns2.Name = "bodies_with_cyl_face" +ns2.Location = selection +selection_manager.ClearSelection() + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Modify material assignment +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Assign a specific material to all bodies in the model +allbodies = Model.GetChildren(DataModelObjectCategory.Body, True) +for body in allbodies: + body.Material = "Structural Steel" + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Get all Coordinate Systems +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Retrieve all coordinate systems in the model +tree_CS = Model.CoordinateSystems + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Add a cylindrical coordinate system +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a new coordinate system +csys = Model.CoordinateSystems.AddCoordinateSystem() +# place csys origin at arbitrary (0,25,50) location +csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) +# set primary X axis to arbitrary (1,2,3) direction +csys.PrimaryAxisDirection = Vector3D(1, 2, 3) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Add a cartesian coordinate system at a location (0,25,50) inches +# with primary X axis towards an arbitrary (1,2,3) direction +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +csys = Model.CoordinateSystems.AddCoordinateSystem() +# place csys origin at arbitrary (0,25,50) location +csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) +# set primary X axis to arbitrary (1,2,3) direction +csys.PrimaryAxisDirection = Vector3D(1, 2, 3) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# %% +# Find a coordinate system by name +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Create a new coordinate system +csys = app.Model.CoordinateSystems.AddCoordinateSystem() +# place csys origin at arbitrary (0,25,50) location +csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) +# set primary X axis to arbitrary (1,2,3) direction +csys.PrimaryAxisDirection = Vector3D(1, 2, 3) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# sphinx_gallery_start_ignore +# Save the Mechanical database file +from pathlib import Path + +output_path = Path.cwd() / "out" +test_mechdat_path = str(output_path / "test.mechdat") +# app.save_as(test_mechdat_path, overwrite=True) + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# Close the application and delete downloaded files +app.close() +delete_downloads() +# sphinx_gallery_end_ignore + +# Get current and peak memory usage +current, peak = tracemalloc.get_traced_memory() +print(f"Current memory usage: {current / 1024:.2f} KiB") +print(f"Peak memory usage: {peak / 1024:.2f} KiB") + +# stop tracing memory +tracemalloc.stop() diff --git a/examples/00_setup/02_setup.py b/examples/00_setup/02_setup.py deleted file mode 100644 index e498840df..000000000 --- a/examples/00_setup/02_setup.py +++ /dev/null @@ -1,171 +0,0 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -""".. _ref_setup_2: - -App ---- - -This section has helper scripts to start an embedded instance of Mechanical -Application and import/open a file. - -This is a prerequisite step for the other helper scripts in the following pages. - - -""" - -import tracemalloc - -# Start tracing memory -tracemalloc.start() - -# %% -# Create an embedded instance and open an existing Mechanical File -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -from ansys.mechanical.core import App -from ansys.mechanical.core.examples import delete_downloads, download_file - -mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# The following line creates an instance of the app, extracts the global API entry points, -# and merges them into your Python global variables. - -app = App(db_file=mechdat_path, globals=globals()) -print(app) - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# Alternatively, you can use the update_globals method of the App class to -# update the global variables.The second argument, if set to False updates -# globals without enums like "SelectionTypeEnum" or "LoadDefineBy" -# app = App() -# app.update_globals(globals(), False) - -# For a specific version , use ; -# app = App(version=241) - -# %% -# Import a Geometry File -# ~~~~~~~~~~~~~~~~~~~~~~ - -# sphinx_gallery_start_ignore -app.new() -# sphinx_gallery_end_ignore - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") -geometry_import = Model.GeometryImportGroup.AddGeometryImport() -geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic -geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() -geometry_import_preferences.ProcessLines = True -geometry_import_preferences.NamedSelectionKey = "" -geometry_import_preferences.ProcessNamedSelections = True -geometry_import_preferences.ProcessMaterialProperties = True -geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") -# %% -# Set Units -# ~~~~~~~~~~~~~~~~~~~~~~~ - -ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM -ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian -ExtAPI.Application.ActiveAngularVelocityUnit = AngularVelocityUnitType.RadianPerSecond - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") -# %% -# View messages in Mechanical using PyMechanical -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -app.messages.show() - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") -# %% -# Plot and Print the Tree (To check model so far) -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -# Plot -app.plot() - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# Print the tree -app.print_tree() - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# %% -# Save the model -# ~~~~~~~~~~~~~~~ -from pathlib import Path - -output_path = Path.cwd() / "out" -test_mechdat_path = str(output_path / "test.mechdat") -app.save_as(test_mechdat_path, overwrite=True) - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# sphinx_gallery_start_ignore -# Close the app -app.close() -# Delete the downloaded files -delete_downloads() -# sphinx_gallery_end_ignore - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# stop tracing memory -tracemalloc.stop() diff --git a/examples/00_setup/03_setup.py b/examples/00_setup/03_setup.py deleted file mode 100644 index efff44dac..000000000 --- a/examples/00_setup/03_setup.py +++ /dev/null @@ -1,171 +0,0 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -""".. _ref_setup_3: - -App ---- - -This section has helper scripts to start an embedded instance of Mechanical -Application and import/open a file. - -This is a prerequisite step for the other helper scripts in the following pages. - - -""" - -import tracemalloc - -# Start tracing memory -tracemalloc.start() - -# %% -# Create an embedded instance and open an existing Mechanical File -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -from ansys.mechanical.core import App -from ansys.mechanical.core.examples import delete_downloads, download_file - -mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# The following line creates an instance of the app, extracts the global API entry points, -# and merges them into your Python global variables. - -app = App(db_file=mechdat_path, globals=globals()) -print(app) - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# Alternatively, you can use the update_globals method of the App class to -# update the global variables.The second argument, if set to False updates -# globals without enums like "SelectionTypeEnum" or "LoadDefineBy" -# app = App() -# app.update_globals(globals(), False) - -# For a specific version , use ; -# app = App(version=241) - -# %% -# Import a Geometry File -# ~~~~~~~~~~~~~~~~~~~~~~ - -# sphinx_gallery_start_ignore -app.new() -# sphinx_gallery_end_ignore - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") -geometry_import = Model.GeometryImportGroup.AddGeometryImport() -geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic -geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() -geometry_import_preferences.ProcessLines = True -geometry_import_preferences.NamedSelectionKey = "" -geometry_import_preferences.ProcessNamedSelections = True -geometry_import_preferences.ProcessMaterialProperties = True -geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") -# %% -# Set Units -# ~~~~~~~~~~~~~~~~~~~~~~~ - -ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM -ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian -ExtAPI.Application.ActiveAngularVelocityUnit = AngularVelocityUnitType.RadianPerSecond - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") -# %% -# View messages in Mechanical using PyMechanical -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -app.messages.show() - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") -# %% -# Plot and Print the Tree (To check model so far) -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -# Plot -app.plot() - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# Print the tree -app.print_tree() - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# %% -# Save the model -# ~~~~~~~~~~~~~~~ -from pathlib import Path - -output_path = Path.cwd() / "out" -test_mechdat_path = str(output_path / "test.mechdat") -app.save_as(test_mechdat_path, overwrite=True) - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# sphinx_gallery_start_ignore -# Close the app -app.close() -# Delete the downloaded files -delete_downloads() -# sphinx_gallery_end_ignore - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# stop tracing memory -tracemalloc.stop() From 2df9be966728284aa6ccf8cb07ce6c84b949c506 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Tue, 28 Oct 2025 16:00:26 -0400 Subject: [PATCH 38/52] try all files --- doc/Makefile | 4 +- examples/00_setup/01_setup.py | 58 ---- examples/00_setup/02_geometry.py | 175 ---------- .../00_setup}/03_connections.py | 0 .../00_setup}/04_named_selections.py | 0 .../00_setup}/05_mesh.py | 0 .../00_setup}/06_loads.py | 0 .../00_setup}/07_results.py | 0 .../00_setup}/08_tree_objects.py | 0 examples_save/02_geometry.py | 315 ------------------ 10 files changed, 2 insertions(+), 550 deletions(-) rename {examples_save => examples/00_setup}/03_connections.py (100%) rename {examples_save => examples/00_setup}/04_named_selections.py (100%) rename {examples_save => examples/00_setup}/05_mesh.py (100%) rename {examples_save => examples/00_setup}/06_loads.py (100%) rename {examples_save => examples/00_setup}/07_results.py (100%) rename {examples_save => examples/00_setup}/08_tree_objects.py (100%) delete mode 100644 examples_save/02_geometry.py diff --git a/doc/Makefile b/doc/Makefile index 7fa80c5b0..7e3cf7832 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,7 +1,7 @@ # Minimal makefile for Sphinx documentation # You can set these variables from the command line. -SPHINXOPTS = -j auto +SPHINXOPTS = -j auto -v SPHINXBUILD = sphinx-build SOURCEDIR = source BUILDDIR = _build @@ -16,7 +16,7 @@ help: # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) --verbose + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) # customized clean due to examples gallery clean: diff --git a/examples/00_setup/01_setup.py b/examples/00_setup/01_setup.py index 96fc8b29e..f8ff74f99 100644 --- a/examples/00_setup/01_setup.py +++ b/examples/00_setup/01_setup.py @@ -33,11 +33,6 @@ """ -import tracemalloc - -# Start tracing memory -tracemalloc.start() - # %% # Create an embedded instance and open an existing Mechanical File # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -47,22 +42,12 @@ mechdat_path = download_file("cantilever.mechdat", "pymechanical", "embedding") -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # The following line creates an instance of the app, extracts the global API entry points, # and merges them into your Python global variables. app = App(db_file=mechdat_path, globals=globals()) print(app) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Alternatively, you can use the update_globals method of the App class to # update the global variables.The second argument, if set to False updates # globals without enums like "SelectionTypeEnum" or "LoadDefineBy" @@ -80,11 +65,6 @@ app.new() # sphinx_gallery_end_ignore -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic @@ -94,11 +74,6 @@ geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") # %% # Set Units # ~~~~~~~~~~~~~~~~~~~~~~~ @@ -106,21 +81,11 @@ ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian ExtAPI.Application.ActiveAngularVelocityUnit = AngularVelocityUnitType.RadianPerSecond - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") # %% # View messages in Mechanical using PyMechanical # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ app.messages.show() - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") # %% # Plot and Print the Tree (To check model so far) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -128,19 +93,9 @@ # Plot app.plot() -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Print the tree app.print_tree() -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Save the model # ~~~~~~~~~~~~~~~ @@ -150,22 +105,9 @@ test_mechdat_path = str(output_path / "test.mechdat") app.save_as(test_mechdat_path, overwrite=True) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # sphinx_gallery_start_ignore # Close the app app.close() # Delete the downloaded files delete_downloads() # sphinx_gallery_end_ignore - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# stop tracing memory -tracemalloc.stop() diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index fd5204787..347d4404e 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -31,11 +31,6 @@ simulations. Coordinate Systems too are covered here. """ -import tracemalloc - -# Start tracing memory -tracemalloc.start() - # %% # Import Geometry # ~~~~~~~~~~~~~~~ @@ -45,67 +40,31 @@ app = App(globals=globals()) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Download the geometry file for the example geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") # Alternatively, you can specify a local file path # or geom_file_path = r"C:\geometry.agdb" -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Import the geometry into the Mechanical model geometry_import = Model.GeometryImportGroup.AddGeometryImport() geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Set preferences for geometry import geometry_import_preferences.ProcessLines = True geometry_import_preferences.NamedSelectionKey = "" geometry_import_preferences.ProcessNamedSelections = True geometry_import_preferences.ProcessMaterialProperties = True -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Perform the geometry import geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Plot the imported geometry app.plot() -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Print the tree structure of the Mechanical model app.print_tree() -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - - # %% # Get all bodies # ~~~~~~~~~~~~~~~~~ @@ -115,11 +74,6 @@ # Alternatively, use the following method: # bodies_objects = Model.Geometry.GetChildren(Ansys.ACT.Automation.Mechanical.Body, True) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Extract geometric body wrappers for each body object bodies = [body.GetGeoBody() for body in body_objects] # GeoBodyWrapper # or @@ -127,51 +81,26 @@ # nested_list = [x.Bodies for x in ExtAPI.DataModel.GeoData.Assemblies[0].AllParts] # bodies = list(itertools.chain(*nested_list)) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Access details of the first body object and its geometric properties bo = body_objects[0] # Access Object Details and RMB options b = bodies[0] # Access Geometric Properties: 'Area', 'GeoData', 'Centroid', 'Faces', etc. -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Find Body with Largest Volume # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Set the active unit system to Standard NMM ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Create a list of body names, volumes, and IDs for unsuppressed bodies body_names_volumes = [] for body in body_objects: if body.Suppressed == 0 and body.Volume: body_names_volumes.append((body.Name, body.Volume, body.GetGeoBody().Id)) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Sort the list and retrieve the body with the largest volume sorted_name_vol = sorted(body_names_volumes) bodyname, volu, bodyid = sorted_name_vol.pop() -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Print details of the largest body print(f"Unit System is: {ExtAPI.Application.ActiveUnitSystem}") print(f"Name of the Largest Body: '{bodyname}'") @@ -185,11 +114,6 @@ b2 = DataModel.GeoData.GeoEntityById(bodyid) print(f"Body Name: {b2.Name}, Body Id: {b2.Id}") -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Find the Part that the body belongs to # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -198,11 +122,6 @@ part_name = DataModel.GeoData.GeoEntityById(59).Part.Name print(f"The Body named '{body_name}' belongs to the part named '{part_name}'") -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Find Body by its ID AND print its Faces, Centroid, etc. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -231,11 +150,6 @@ vertices.append(body.Vertices[i].Id) print(vertices) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Get all edges of a given length # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -246,11 +160,6 @@ geo = DataModel.GeoData edgelist = [] -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Iterate through assemblies, parts, and bodies to find edges of the given length for asm in geo.Assemblies: for part in asm.Parts: @@ -260,11 +169,6 @@ edgelist.append(edge.Id) print(edgelist) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Get all circular edges of a given radius # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -289,11 +193,6 @@ circlelist.append(edge.Id) print(circlelist) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Get Radius of a selected edge # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -302,11 +201,6 @@ my_edge_radius = my_edge.Radius if str(my_edge.CurveType) == "GeoCurveCircle" else 0.0 print(my_edge_radius) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Create a Named Selection from a list of body Ids # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -318,20 +212,10 @@ selection.Ids = mylist selection_manager.NewSelection(selection) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - ns2 = Model.AddNamedSelection() ns2.Name = "bodies2" ns2.Location = selection -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Find a Named Selection with a prefix # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -340,11 +224,6 @@ my_nsel = [i for i in NSall if i.Name.startswith("b")][0] print(my_nsel.Name) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Create a Named Selection of all bodies with a cylindrical face # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -365,30 +244,15 @@ if countcyl != 0: cyl_body_ids.append(body.Id) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - selection_manager = ExtAPI.SelectionManager selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = cyl_body_ids -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - ns2 = Model.AddNamedSelection() ns2.Name = "bodies_with_cyl_face" ns2.Location = selection selection_manager.ClearSelection() -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Modify material assignment # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -397,22 +261,12 @@ for body in allbodies: body.Material = "Structural Steel" -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Get all Coordinate Systems # ~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve all coordinate systems in the model tree_CS = Model.CoordinateSystems -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Add a cylindrical coordinate system # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -422,12 +276,6 @@ csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) # set primary X axis to arbitrary (1,2,3) direction csys.PrimaryAxisDirection = Vector3D(1, 2, 3) - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Add a cartesian coordinate system at a location (0,25,50) inches # with primary X axis towards an arbitrary (1,2,3) direction @@ -438,11 +286,6 @@ # set primary X axis to arbitrary (1,2,3) direction csys.PrimaryAxisDirection = Vector3D(1, 2, 3) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # %% # Find a coordinate system by name # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -453,11 +296,6 @@ # set primary X axis to arbitrary (1,2,3) direction csys.PrimaryAxisDirection = Vector3D(1, 2, 3) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # sphinx_gallery_start_ignore # Save the Mechanical database file from pathlib import Path @@ -466,20 +304,7 @@ test_mechdat_path = str(output_path / "test.mechdat") # app.save_as(test_mechdat_path, overwrite=True) -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - # Close the application and delete downloaded files app.close() delete_downloads() # sphinx_gallery_end_ignore - -# Get current and peak memory usage -current, peak = tracemalloc.get_traced_memory() -print(f"Current memory usage: {current / 1024:.2f} KiB") -print(f"Peak memory usage: {peak / 1024:.2f} KiB") - -# stop tracing memory -tracemalloc.stop() diff --git a/examples_save/03_connections.py b/examples/00_setup/03_connections.py similarity index 100% rename from examples_save/03_connections.py rename to examples/00_setup/03_connections.py diff --git a/examples_save/04_named_selections.py b/examples/00_setup/04_named_selections.py similarity index 100% rename from examples_save/04_named_selections.py rename to examples/00_setup/04_named_selections.py diff --git a/examples_save/05_mesh.py b/examples/00_setup/05_mesh.py similarity index 100% rename from examples_save/05_mesh.py rename to examples/00_setup/05_mesh.py diff --git a/examples_save/06_loads.py b/examples/00_setup/06_loads.py similarity index 100% rename from examples_save/06_loads.py rename to examples/00_setup/06_loads.py diff --git a/examples_save/07_results.py b/examples/00_setup/07_results.py similarity index 100% rename from examples_save/07_results.py rename to examples/00_setup/07_results.py diff --git a/examples_save/08_tree_objects.py b/examples/00_setup/08_tree_objects.py similarity index 100% rename from examples_save/08_tree_objects.py rename to examples/00_setup/08_tree_objects.py diff --git a/examples_save/02_geometry.py b/examples_save/02_geometry.py deleted file mode 100644 index fa78225d0..000000000 --- a/examples_save/02_geometry.py +++ /dev/null @@ -1,315 +0,0 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -""".. _ref_geometry: - -Geometry --------- - -This section contains a few utility scripts for working with Geometry, -including importing, analyzing, and accessing geometric data, as well -as utilizing it for downstream preprocessing operations in Mechanical -simulations. Coordinate Systems too are covered here. -""" - -# %% -# Import Geometry -# ~~~~~~~~~~~~~~~ - -from ansys.mechanical.core import App -from ansys.mechanical.core.examples import delete_downloads, download_file - -app = App(globals=globals()) - -# Download the geometry file for the example -geom_file_path = download_file("example_06_bolt_pret_geom.agdb", "pymechanical", "00_basic") -# Alternatively, you can specify a local file path -# or geom_file_path = r"C:\geometry.agdb" - -# Import the geometry into the Mechanical model -geometry_import = Model.GeometryImportGroup.AddGeometryImport() -geometry_import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic -geometry_import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() - -# Set preferences for geometry import -geometry_import_preferences.ProcessLines = True -geometry_import_preferences.NamedSelectionKey = "" -geometry_import_preferences.ProcessNamedSelections = True -geometry_import_preferences.ProcessMaterialProperties = True - -# Perform the geometry import -geometry_import.Import(geom_file_path, geometry_import_format, geometry_import_preferences) - -# Plot the imported geometry -app.plot() - -# Print the tree structure of the Mechanical model -app.print_tree() - - -# %% -# Get all bodies -# ~~~~~~~~~~~~~~~~~ - -# Retrieve all body objects from the geometry -body_objects = Model.Geometry.GetChildren(DataModelObjectCategory.Body, True) -# Alternatively, use the following method: -# bodies_objects = Model.Geometry.GetChildren(Ansys.ACT.Automation.Mechanical.Body, True) - -# Extract geometric body wrappers for each body object -bodies = [body.GetGeoBody() for body in body_objects] # GeoBodyWrapper -# or -# import itertools -# nested_list = [x.Bodies for x in ExtAPI.DataModel.GeoData.Assemblies[0].AllParts] -# bodies = list(itertools.chain(*nested_list)) - -# Access details of the first body object and its geometric properties -bo = body_objects[0] # Access Object Details and RMB options -b = bodies[0] # Access Geometric Properties: 'Area', 'GeoData', 'Centroid', 'Faces', etc. - -# %% -# Find Body with Largest Volume -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Set the active unit system to Standard NMM -ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM - -# Create a list of body names, volumes, and IDs for unsuppressed bodies -body_names_volumes = [] -for body in body_objects: - if body.Suppressed == 0 and body.Volume: - body_names_volumes.append((body.Name, body.Volume, body.GetGeoBody().Id)) - -# Sort the list and retrieve the body with the largest volume -sorted_name_vol = sorted(body_names_volumes) -bodyname, volu, bodyid = sorted_name_vol.pop() - -# Print details of the largest body -print(f"Unit System is: {ExtAPI.Application.ActiveUnitSystem}") -print(f"Name of the Largest Body: '{bodyname}'") -print(f"Its Volume: {round(volu.Value, 2)} {volu.Unit}") -print(f"Its id: {bodyid}") - -# %% -# Find Body by its ID -# ~~~~~~~~~~~~~~~~~~~~~~ -# Retrieve a body object using its ID -b2 = DataModel.GeoData.GeoEntityById(bodyid) -print(f"Body Name: {b2.Name}, Body Id: {b2.Id}") - -# %% -# Find the Part that the body belongs to -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Retrieve the name of a body and the part it belongs to using its ID -body_name = DataModel.GeoData.GeoEntityById(59).Name -part_name = DataModel.GeoData.GeoEntityById(59).Part.Name -print(f"The Body named '{body_name}' belongs to the part named '{part_name}'") - -# %% -# Find Body by its ID AND print its Faces, Centroid, etc. -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Retrieve a body object and its faces, centroids, etc. -body2 = DataModel.GeoData.GeoEntityById(bodyid) - -# Get face IDs and centroids for each face -face_ids = [face.Id for face in body2.Faces] -centroids_of_each_face = [DataModel.GeoData.GeoEntityById(face_id).Centroid for face_id in face_ids] - -# Print face IDs and their centroids -for face_id, centroid in zip(face_ids, centroids_of_each_face): - print(face_id, list(centroid)) - -# %% -# Get all Vertices -# ~~~~~~~~~~~~~~~~~~~ - -# Retrieve all vertex IDs from the geometry -vertices = [] -geo = DataModel.GeoData -for asm in geo.Assemblies: - for part in asm.Parts: - for body in part.Bodies: - for i in range(0, body.Vertices.Count): - vertices.append(body.Vertices[i].Id) -print(vertices) - -# %% -# Get all edges of a given length -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Retrieve all edges with a specified length -ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM -use_length = 0.100 - -geo = DataModel.GeoData -edgelist = [] - -# Iterate through assemblies, parts, and bodies to find edges of the given length -for asm in geo.Assemblies: - for part in asm.Parts: - for body in part.Bodies: - for edge in body.Edges: - if abs(edge.Length - use_length) <= use_length * 0.01: - edgelist.append(edge.Id) -print(edgelist) - -# %% -# Get all circular edges of a given radius -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Retrieve all circular edges with a specified radius -import math - -radius = 0.018 # Target radius -circumference = 2 * math.pi * radius # Calculate circumference - -geo = DataModel.GeoData -circlelist = [] - -# Iterate through assemblies, parts, and bodies to find circular edges -for asm in geo.Assemblies: - for part in asm.Parts: - for body in part.Bodies: - for edge in body.Edges: - if ( - abs(edge.Length - circumference) <= circumference * 0.01 - and str(edge.CurveType) == "GeoCurveCircle" - ): - circlelist.append(edge.Id) -print(circlelist) - -# %% -# Get Radius of a selected edge -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Retrieve the radius of a specific edge if it is circular -my_edge = DataModel.GeoData.GeoEntityById(27) -my_edge_radius = my_edge.Radius if str(my_edge.CurveType) == "GeoCurveCircle" else 0.0 -print(my_edge_radius) - -# %% -# Create a Named Selection from a list of body Ids -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a named selection for a list of body IDs -mylist = [bodyid] - -selection_manager = ExtAPI.SelectionManager -selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -selection.Ids = mylist -selection_manager.NewSelection(selection) - -ns2 = Model.AddNamedSelection() -ns2.Name = "bodies2" -ns2.Location = selection - -# %% -# Find a Named Selection with a prefix -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Retrieve a named selection whose name starts with a specific prefix -NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) -my_nsel = [i for i in NSall if i.Name.startswith("b")][0] -print(my_nsel.Name) - -# %% -# Create a Named Selection of all bodies with a cylindrical face -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -geo = DataModel.GeoData -cyl_body_ids = [] - -for asm in geo.Assemblies: - for part in asm.Parts: - for body in part.Bodies: - countcyl = 0 - for face in body.Faces: - if ( - face.SurfaceType - == Ansys.ACT.Interfaces.Geometry.GeoSurfaceTypeEnum.GeoSurfaceCylinder - ): - countcyl = countcyl + 1 - if countcyl != 0: - cyl_body_ids.append(body.Id) - -selection_manager = ExtAPI.SelectionManager -selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) -selection.Ids = cyl_body_ids - -ns2 = Model.AddNamedSelection() -ns2.Name = "bodies_with_cyl_face" -ns2.Location = selection -selection_manager.ClearSelection() - -# %% -# Modify material assignment -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Assign a specific material to all bodies in the model -allbodies = Model.GetChildren(DataModelObjectCategory.Body, True) -for body in allbodies: - body.Material = "Structural Steel" - -# %% -# Get all Coordinate Systems -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Retrieve all coordinate systems in the model -tree_CS = Model.CoordinateSystems - -# %% -# Add a cylindrical coordinate system -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a new coordinate system -csys = Model.CoordinateSystems.AddCoordinateSystem() -# place csys origin at arbitrary (0,25,50) location -csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) -# set primary X axis to arbitrary (1,2,3) direction -csys.PrimaryAxisDirection = Vector3D(1, 2, 3) - -# %% -# Add a cartesian coordinate system at a location (0,25,50) inches -# with primary X axis towards an arbitrary (1,2,3) direction -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -csys = Model.CoordinateSystems.AddCoordinateSystem() -# place csys origin at arbitrary (0,25,50) location -csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) -# set primary X axis to arbitrary (1,2,3) direction -csys.PrimaryAxisDirection = Vector3D(1, 2, 3) - - -# %% -# Find a coordinate system by name -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a new coordinate system -csys = app.Model.CoordinateSystems.AddCoordinateSystem() -# place csys origin at arbitrary (0,25,50) location -csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) -# set primary X axis to arbitrary (1,2,3) direction -csys.PrimaryAxisDirection = Vector3D(1, 2, 3) - - -# sphinx_gallery_start_ignore -# Save the Mechanical database file -from pathlib import Path - -output_path = Path.cwd() / "out" -test_mechdat_path = str(output_path / "test.mechdat") -# app.save_as(test_mechdat_path, overwrite=True) - - -# Close the application and delete downloaded files -app.close() -delete_downloads() -# sphinx_gallery_end_ignore From 90e211abb6c66f028f5b28b9ec61786c92811040 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Tue, 28 Oct 2025 16:11:36 -0400 Subject: [PATCH 39/52] fix missing dep --- .github/workflows/ci_cd.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 716d68fb8..596bd2262 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -208,22 +208,22 @@ jobs: # echo "matrix={\"mechanical-version\":['${{ needs.revn-variations.outputs.test_docker_image_version }}'],\"experimental\":[false]}" >> $GITHUB_OUTPUT # fi - # container-stability-check: - # runs-on: ubuntu-latest - # needs: [revn-variations] - # outputs: - # container_stable_exit: ${{ steps.check_stability.outputs.container_stable_exit }} - # steps: - # - id: check_stability - # run: | - # sudo apt update - # sudo apt install bc -y - # container_version=$(echo "${{ needs.revn-variations.outputs.test_docker_image_version }}" | grep -o -E '[0-9]+(\.[0-9]+)?' | head -n 1) - # if (( $(echo "$container_version > 24.2" | bc -l) )); then - # echo "container_stable_exit=true" >> $GITHUB_OUTPUT - # else - # echo "container_stable_exit=false" >> $GITHUB_OUTPUT - # fi + container-stability-check: + runs-on: ubuntu-latest + needs: [revn-variations] + outputs: + container_stable_exit: ${{ steps.check_stability.outputs.container_stable_exit }} + steps: + - id: check_stability + run: | + sudo apt update + sudo apt install bc -y + container_version=$(echo "${{ needs.revn-variations.outputs.test_docker_image_version }}" | grep -o -E '[0-9]+(\.[0-9]+)?' | head -n 1) + if (( $(echo "$container_version > 24.2" | bc -l) )); then + echo "container_stable_exit=true" >> $GITHUB_OUTPUT + else + echo "container_stable_exit=false" >> $GITHUB_OUTPUT + fi # remote-connect: # name: Remote connect testing and coverage - Mechanical ${{ matrix.mechanical-version }} @@ -572,7 +572,7 @@ jobs: container: image: ${{ needs.revn-variations.outputs.test_container }} options: --entrypoint /bin/bash - needs: [revn-variations] + needs: [revn-variations, container-stability-check] #needs: [style, doc-style, revn-variations, container-stability-check, test-container-info] steps: From 5732fa1d8a5b75def1da301b393503db0ce50a68 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Wed, 29 Oct 2025 12:13:18 -0400 Subject: [PATCH 40/52] test single example --- {examples/00_setup => examples_save}/02_geometry.py | 0 {examples/00_setup => examples_save}/03_connections.py | 0 {examples/00_setup => examples_save}/04_named_selections.py | 0 {examples/00_setup => examples_save}/05_mesh.py | 0 {examples/00_setup => examples_save}/06_loads.py | 0 {examples/00_setup => examples_save}/07_results.py | 0 {examples/00_setup => examples_save}/08_tree_objects.py | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename {examples/00_setup => examples_save}/02_geometry.py (100%) rename {examples/00_setup => examples_save}/03_connections.py (100%) rename {examples/00_setup => examples_save}/04_named_selections.py (100%) rename {examples/00_setup => examples_save}/05_mesh.py (100%) rename {examples/00_setup => examples_save}/06_loads.py (100%) rename {examples/00_setup => examples_save}/07_results.py (100%) rename {examples/00_setup => examples_save}/08_tree_objects.py (100%) diff --git a/examples/00_setup/02_geometry.py b/examples_save/02_geometry.py similarity index 100% rename from examples/00_setup/02_geometry.py rename to examples_save/02_geometry.py diff --git a/examples/00_setup/03_connections.py b/examples_save/03_connections.py similarity index 100% rename from examples/00_setup/03_connections.py rename to examples_save/03_connections.py diff --git a/examples/00_setup/04_named_selections.py b/examples_save/04_named_selections.py similarity index 100% rename from examples/00_setup/04_named_selections.py rename to examples_save/04_named_selections.py diff --git a/examples/00_setup/05_mesh.py b/examples_save/05_mesh.py similarity index 100% rename from examples/00_setup/05_mesh.py rename to examples_save/05_mesh.py diff --git a/examples/00_setup/06_loads.py b/examples_save/06_loads.py similarity index 100% rename from examples/00_setup/06_loads.py rename to examples_save/06_loads.py diff --git a/examples/00_setup/07_results.py b/examples_save/07_results.py similarity index 100% rename from examples/00_setup/07_results.py rename to examples_save/07_results.py diff --git a/examples/00_setup/08_tree_objects.py b/examples_save/08_tree_objects.py similarity index 100% rename from examples/00_setup/08_tree_objects.py rename to examples_save/08_tree_objects.py From 2dccf799b788174b4b3474864baa5add8a7c9aa3 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Wed, 29 Oct 2025 13:19:42 -0400 Subject: [PATCH 41/52] add second setup example --- {examples_save => examples/00_setup}/02_geometry.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {examples_save => examples/00_setup}/02_geometry.py (100%) diff --git a/examples_save/02_geometry.py b/examples/00_setup/02_geometry.py similarity index 100% rename from examples_save/02_geometry.py rename to examples/00_setup/02_geometry.py From a5d96168bd9133e94d9875382c8cc4d9e1613e82 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Wed, 29 Oct 2025 14:04:48 -0400 Subject: [PATCH 42/52] only test geometry --- examples/00_setup/02_geometry.py | 12 ++++++------ {examples/00_setup => examples_save}/01_setup.py | 0 2 files changed, 6 insertions(+), 6 deletions(-) rename {examples/00_setup => examples_save}/01_setup.py (100%) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 347d4404e..3ae47a7af 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -134,7 +134,7 @@ # Print face IDs and their centroids for face_id, centroid in zip(face_ids, centroids_of_each_face): - print(face_id, list(centroid)) + print(f"Face ID: {face_id}", f"List: {list(centroid)}") # %% # Get all Vertices @@ -148,7 +148,7 @@ for body in part.Bodies: for i in range(0, body.Vertices.Count): vertices.append(body.Vertices[i].Id) -print(vertices) +print(f"Vertices: {vertices}") # %% # Get all edges of a given length @@ -167,7 +167,7 @@ for edge in body.Edges: if abs(edge.Length - use_length) <= use_length * 0.01: edgelist.append(edge.Id) -print(edgelist) +print(f"Edgelist: {edgelist}") # %% # Get all circular edges of a given radius @@ -191,7 +191,7 @@ and str(edge.CurveType) == "GeoCurveCircle" ): circlelist.append(edge.Id) -print(circlelist) +print(f"Circle list: {circlelist}") # %% # Get Radius of a selected edge @@ -199,7 +199,7 @@ # Retrieve the radius of a specific edge if it is circular my_edge = DataModel.GeoData.GeoEntityById(27) my_edge_radius = my_edge.Radius if str(my_edge.CurveType) == "GeoCurveCircle" else 0.0 -print(my_edge_radius) +print(f"Edge radius is: {my_edge_radius}") # %% # Create a Named Selection from a list of body Ids @@ -222,7 +222,7 @@ # Retrieve a named selection whose name starts with a specific prefix NSall = Model.NamedSelections.GetChildren[Ansys.ACT.Automation.Mechanical.NamedSelection](True) my_nsel = [i for i in NSall if i.Name.startswith("b")][0] -print(my_nsel.Name) +print(f"Named selection name: {my_nsel.Name}") # %% # Create a Named Selection of all bodies with a cylindrical face diff --git a/examples/00_setup/01_setup.py b/examples_save/01_setup.py similarity index 100% rename from examples/00_setup/01_setup.py rename to examples_save/01_setup.py From 3e0f50210c26ef512f876383269b2cfae9313f18 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Wed, 29 Oct 2025 14:31:26 -0400 Subject: [PATCH 43/52] add more print statements --- examples/00_setup/02_geometry.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 3ae47a7af..46eba6044 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -235,15 +235,18 @@ for part in asm.Parts: for body in part.Bodies: countcyl = 0 + print(f"countcyl {countcyl} for body {body}") for face in body.Faces: if ( face.SurfaceType == Ansys.ACT.Interfaces.Geometry.GeoSurfaceTypeEnum.GeoSurfaceCylinder ): - countcyl = countcyl + 1 + countcyl+=1 if countcyl != 0: cyl_body_ids.append(body.Id) +print(f"Bodies with cylindrical face IDs: {cyl_body_ids}") + selection_manager = ExtAPI.SelectionManager selection = ExtAPI.SelectionManager.CreateSelectionInfo(SelectionTypeEnum.GeometryEntities) selection.Ids = cyl_body_ids @@ -253,6 +256,8 @@ ns2.Location = selection selection_manager.ClearSelection() +print("Cleared selection") + # %% # Modify material assignment # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -272,6 +277,9 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Create a new coordinate system csys = Model.CoordinateSystems.AddCoordinateSystem() + +print("Added coordinate system") + # place csys origin at arbitrary (0,25,50) location csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) # set primary X axis to arbitrary (1,2,3) direction @@ -291,6 +299,9 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Create a new coordinate system csys = app.Model.CoordinateSystems.AddCoordinateSystem() + +print("Added 2nd coordinate system") + # place csys origin at arbitrary (0,25,50) location csys.SetOriginLocation(Quantity(0, "in"), Quantity(25, "in"), Quantity(50, "in")) # set primary X axis to arbitrary (1,2,3) direction From 0f2c15b77eb08092f23bc973e3ca21f4b03aa33b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 18:31:41 +0000 Subject: [PATCH 44/52] chore: auto fixes from pre-commit hooks --- examples/00_setup/02_geometry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 46eba6044..47009790b 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -241,7 +241,7 @@ face.SurfaceType == Ansys.ACT.Interfaces.Geometry.GeoSurfaceTypeEnum.GeoSurfaceCylinder ): - countcyl+=1 + countcyl += 1 if countcyl != 0: cyl_body_ids.append(body.Id) From b4ed87d65263c4a63cfbe08094b76cc53ab2a8d3 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Wed, 29 Oct 2025 14:57:34 -0400 Subject: [PATCH 45/52] add more print statements --- examples/00_setup/02_geometry.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 46eba6044..765bd673b 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -241,7 +241,7 @@ face.SurfaceType == Ansys.ACT.Interfaces.Geometry.GeoSurfaceTypeEnum.GeoSurfaceCylinder ): - countcyl+=1 + countcyl += 1 if countcyl != 0: cyl_body_ids.append(body.Id) @@ -313,9 +313,18 @@ output_path = Path.cwd() / "out" test_mechdat_path = str(output_path / "test.mechdat") -# app.save_as(test_mechdat_path, overwrite=True) +print("Set mechdat path") + +app.save_as(test_mechdat_path, overwrite=True) + +print("Saved mechdat") # Close the application and delete downloaded files app.close() + +print("Closed app") + delete_downloads() + +print("Deleted downloads") # sphinx_gallery_end_ignore From 11318aa3d852e5b6b405f2cab65fff47da803c43 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Wed, 29 Oct 2025 15:24:36 -0400 Subject: [PATCH 46/52] enable pdb debugging --- doc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Makefile b/doc/Makefile index 7e3cf7832..4f0e2324f 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,7 +1,7 @@ # Minimal makefile for Sphinx documentation # You can set these variables from the command line. -SPHINXOPTS = -j auto -v +SPHINXOPTS = -j auto -v --pdb SPHINXBUILD = sphinx-build SOURCEDIR = source BUILDDIR = _build From deb9dcf373b35435f166071832b1b55d7efcb3a4 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Wed, 29 Oct 2025 15:39:42 -0400 Subject: [PATCH 47/52] move sphinx gallery ignore --- examples/00_setup/02_geometry.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 765bd673b..c2cfa55c6 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -307,7 +307,6 @@ # set primary X axis to arbitrary (1,2,3) direction csys.PrimaryAxisDirection = Vector3D(1, 2, 3) -# sphinx_gallery_start_ignore # Save the Mechanical database file from pathlib import Path @@ -316,15 +315,11 @@ print("Set mechdat path") app.save_as(test_mechdat_path, overwrite=True) - print("Saved mechdat") - +# sphinx_gallery_start_ignore # Close the application and delete downloaded files app.close() - print("Closed app") - delete_downloads() - print("Deleted downloads") # sphinx_gallery_end_ignore From 783478ca2075725b1ef27a2c082ecca0df3f7d00 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Wed, 29 Oct 2025 16:07:32 -0400 Subject: [PATCH 48/52] add debugging to mechanical app --- examples/00_setup/02_geometry.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index c2cfa55c6..5f330a914 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -37,6 +37,10 @@ from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file +import logging +from ansys.mechanical.core.embedding.logger import Configuration + +Configuration.configure(level=logging.DEBUG, to_stdout=True, base_directory=None) app = App(globals=globals()) From 4d3452af5f7bfb46f4644a6d36d8d494ecb04d02 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 20:07:47 +0000 Subject: [PATCH 49/52] chore: auto fixes from pre-commit hooks --- examples/00_setup/02_geometry.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 5f330a914..fb82f2283 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -35,10 +35,11 @@ # Import Geometry # ~~~~~~~~~~~~~~~ -from ansys.mechanical.core import App -from ansys.mechanical.core.examples import delete_downloads, download_file import logging + +from ansys.mechanical.core import App from ansys.mechanical.core.embedding.logger import Configuration +from ansys.mechanical.core.examples import delete_downloads, download_file Configuration.configure(level=logging.DEBUG, to_stdout=True, base_directory=None) From 8ba64bbdbe61c6f79f170f5d06af257650c4634b Mon Sep 17 00:00:00 2001 From: kmcadams Date: Wed, 29 Oct 2025 16:26:28 -0400 Subject: [PATCH 50/52] save instead of save as --- examples/00_setup/02_geometry.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/00_setup/02_geometry.py b/examples/00_setup/02_geometry.py index 5f330a914..ec5901bf2 100644 --- a/examples/00_setup/02_geometry.py +++ b/examples/00_setup/02_geometry.py @@ -35,10 +35,11 @@ # Import Geometry # ~~~~~~~~~~~~~~~ -from ansys.mechanical.core import App -from ansys.mechanical.core.examples import delete_downloads, download_file import logging + +from ansys.mechanical.core import App from ansys.mechanical.core.embedding.logger import Configuration +from ansys.mechanical.core.examples import delete_downloads, download_file Configuration.configure(level=logging.DEBUG, to_stdout=True, base_directory=None) @@ -318,7 +319,7 @@ test_mechdat_path = str(output_path / "test.mechdat") print("Set mechdat path") -app.save_as(test_mechdat_path, overwrite=True) +app.save(test_mechdat_path) print("Saved mechdat") # sphinx_gallery_start_ignore # Close the application and delete downloaded files From 826895816b8bd54a8f9e21dbb9dbfcd5430f2a99 Mon Sep 17 00:00:00 2001 From: kmcadams Date: Thu, 30 Oct 2025 10:16:36 -0400 Subject: [PATCH 51/52] run all examples except 02_geometry --- {examples_save => examples/00_setup}/01_setup.py | 0 {examples_save => examples/00_setup}/03_connections.py | 0 {examples_save => examples/00_setup}/04_named_selections.py | 0 {examples_save => examples/00_setup}/05_mesh.py | 0 {examples_save => examples/00_setup}/06_loads.py | 0 {examples_save => examples/00_setup}/07_results.py | 0 {examples_save => examples/00_setup}/08_tree_objects.py | 0 {examples/00_setup => examples_save}/02_geometry.py | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename {examples_save => examples/00_setup}/01_setup.py (100%) rename {examples_save => examples/00_setup}/03_connections.py (100%) rename {examples_save => examples/00_setup}/04_named_selections.py (100%) rename {examples_save => examples/00_setup}/05_mesh.py (100%) rename {examples_save => examples/00_setup}/06_loads.py (100%) rename {examples_save => examples/00_setup}/07_results.py (100%) rename {examples_save => examples/00_setup}/08_tree_objects.py (100%) rename {examples/00_setup => examples_save}/02_geometry.py (100%) diff --git a/examples_save/01_setup.py b/examples/00_setup/01_setup.py similarity index 100% rename from examples_save/01_setup.py rename to examples/00_setup/01_setup.py diff --git a/examples_save/03_connections.py b/examples/00_setup/03_connections.py similarity index 100% rename from examples_save/03_connections.py rename to examples/00_setup/03_connections.py diff --git a/examples_save/04_named_selections.py b/examples/00_setup/04_named_selections.py similarity index 100% rename from examples_save/04_named_selections.py rename to examples/00_setup/04_named_selections.py diff --git a/examples_save/05_mesh.py b/examples/00_setup/05_mesh.py similarity index 100% rename from examples_save/05_mesh.py rename to examples/00_setup/05_mesh.py diff --git a/examples_save/06_loads.py b/examples/00_setup/06_loads.py similarity index 100% rename from examples_save/06_loads.py rename to examples/00_setup/06_loads.py diff --git a/examples_save/07_results.py b/examples/00_setup/07_results.py similarity index 100% rename from examples_save/07_results.py rename to examples/00_setup/07_results.py diff --git a/examples_save/08_tree_objects.py b/examples/00_setup/08_tree_objects.py similarity index 100% rename from examples_save/08_tree_objects.py rename to examples/00_setup/08_tree_objects.py diff --git a/examples/00_setup/02_geometry.py b/examples_save/02_geometry.py similarity index 100% rename from examples/00_setup/02_geometry.py rename to examples_save/02_geometry.py From 55e26209e310c89f905aa1074d8f7b1867291cfe Mon Sep 17 00:00:00 2001 From: kmcadams Date: Thu, 30 Oct 2025 10:48:17 -0400 Subject: [PATCH 52/52] move 04_named_selections --- {examples/00_setup => examples_save}/04_named_selections.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {examples/00_setup => examples_save}/04_named_selections.py (100%) diff --git a/examples/00_setup/04_named_selections.py b/examples_save/04_named_selections.py similarity index 100% rename from examples/00_setup/04_named_selections.py rename to examples_save/04_named_selections.py