From 0701f73c65acd0ef0acff9bffa5c6c2126b3e2c2 Mon Sep 17 00:00:00 2001 From: Maxime Graulich <maxime.graulich@gmail.com> Date: Tue, 14 May 2013 09:28:07 +0000 Subject: [PATCH] Add Android project --- contrib/mobile/Android/AndroidManifest.xml | 32 + .../res/drawable-hdpi/ic_action_search.png | Bin 0 -> 555 bytes .../Android/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 865 bytes .../Android/res/drawable-hdpi/ic_list.png | Bin 0 -> 464 bytes .../Android/res/drawable-hdpi/ic_mesh.png | Bin 0 -> 760 bytes .../Android/res/drawable-hdpi/ic_settings.png | Bin 0 -> 1412 bytes .../Android/res/drawable-ldpi/ic_launcher.png | Bin 0 -> 384 bytes .../res/drawable-mdpi/ic_action_search.png | Bin 0 -> 3030 bytes .../Android/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 614 bytes .../Android/res/drawable-mdpi/model.png | Bin 0 -> 1116 bytes .../Android/res/drawable-mdpi/param.png | Bin 0 -> 3371 bytes .../mobile/Android/res/layout/list_header.xml | 13 + contrib/mobile/Android/res/layout/model.xml | 35 + contrib/mobile/Android/res/raw/bh_pro | 59 ++ .../Android/res/raw/machine_magstadyn_a_pro | 938 ++++++++++++++++++ .../mobile/Android/res/raw/magnet_data_pro | 16 + contrib/mobile/Android/res/raw/magnet_geo | 93 ++ contrib/mobile/Android/res/raw/magnet_pro | 69 ++ .../mobile/Android/res/raw/magnetostatics_pro | 209 ++++ .../Android/res/raw/pmsm_8p_circuit_pro | 123 +++ contrib/mobile/Android/res/raw/pmsm_data_geo | 104 ++ contrib/mobile/Android/res/raw/pmsm_geo | 95 ++ contrib/mobile/Android/res/raw/pmsm_geo_pro | 211 ++++ contrib/mobile/Android/res/raw/pmsm_pro | 211 ++++ contrib/mobile/Android/res/raw/pmsm_rotor_geo | 163 +++ .../mobile/Android/res/raw/pmsm_stator_geo | 215 ++++ contrib/mobile/Android/res/raw/test_geo | 64 ++ .../mobile/Android/res/values-v11/styles.xml | 5 + .../mobile/Android/res/values-v14/styles.xml | 5 + contrib/mobile/Android/res/values/strings.xml | 25 + contrib/mobile/Android/res/values/styles.xml | 5 + contrib/mobile/Android/res/xml/models.xml | 21 + .../src/org/geuz/onelab/GLESRender.java | 45 + .../Android/src/org/geuz/onelab/Gmsh.java | 90 ++ .../src/org/geuz/onelab/MainActivity.java | 806 +++++++++++++++ .../org/geuz/onelab/ModeleArrayAdapter.java | 54 + .../Android/src/org/geuz/onelab/Models.java | 40 + .../src/org/geuz/onelab/Parameter.java | 85 ++ .../src/org/geuz/onelab/ParameterNumber.java | 270 +++++ .../src/org/geuz/onelab/ParameterString.java | 152 +++ .../org/geuz/onelab/SeparatedListView.java | 144 +++ .../src/org/geuz/onelab/mGLSurfaceView.java | 133 +++ 42 files changed, 4530 insertions(+) create mode 100644 contrib/mobile/Android/AndroidManifest.xml create mode 100644 contrib/mobile/Android/res/drawable-hdpi/ic_action_search.png create mode 100644 contrib/mobile/Android/res/drawable-hdpi/ic_launcher.png create mode 100644 contrib/mobile/Android/res/drawable-hdpi/ic_list.png create mode 100644 contrib/mobile/Android/res/drawable-hdpi/ic_mesh.png create mode 100644 contrib/mobile/Android/res/drawable-hdpi/ic_settings.png create mode 100644 contrib/mobile/Android/res/drawable-ldpi/ic_launcher.png create mode 100644 contrib/mobile/Android/res/drawable-mdpi/ic_action_search.png create mode 100644 contrib/mobile/Android/res/drawable-mdpi/ic_launcher.png create mode 100644 contrib/mobile/Android/res/drawable-mdpi/model.png create mode 100644 contrib/mobile/Android/res/drawable-mdpi/param.png create mode 100644 contrib/mobile/Android/res/layout/list_header.xml create mode 100644 contrib/mobile/Android/res/layout/model.xml create mode 100644 contrib/mobile/Android/res/raw/bh_pro create mode 100644 contrib/mobile/Android/res/raw/machine_magstadyn_a_pro create mode 100644 contrib/mobile/Android/res/raw/magnet_data_pro create mode 100644 contrib/mobile/Android/res/raw/magnet_geo create mode 100644 contrib/mobile/Android/res/raw/magnet_pro create mode 100644 contrib/mobile/Android/res/raw/magnetostatics_pro create mode 100644 contrib/mobile/Android/res/raw/pmsm_8p_circuit_pro create mode 100644 contrib/mobile/Android/res/raw/pmsm_data_geo create mode 100644 contrib/mobile/Android/res/raw/pmsm_geo create mode 100644 contrib/mobile/Android/res/raw/pmsm_geo_pro create mode 100644 contrib/mobile/Android/res/raw/pmsm_pro create mode 100644 contrib/mobile/Android/res/raw/pmsm_rotor_geo create mode 100644 contrib/mobile/Android/res/raw/pmsm_stator_geo create mode 100644 contrib/mobile/Android/res/raw/test_geo create mode 100644 contrib/mobile/Android/res/values-v11/styles.xml create mode 100644 contrib/mobile/Android/res/values-v14/styles.xml create mode 100644 contrib/mobile/Android/res/values/strings.xml create mode 100644 contrib/mobile/Android/res/values/styles.xml create mode 100644 contrib/mobile/Android/res/xml/models.xml create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/GLESRender.java create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/ModeleArrayAdapter.java create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/Models.java create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/Parameter.java create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/ParameterNumber.java create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/ParameterString.java create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/SeparatedListView.java create mode 100644 contrib/mobile/Android/src/org/geuz/onelab/mGLSurfaceView.java diff --git a/contrib/mobile/Android/AndroidManifest.xml b/contrib/mobile/Android/AndroidManifest.xml new file mode 100644 index 0000000000..ce2626134e --- /dev/null +++ b/contrib/mobile/Android/AndroidManifest.xml @@ -0,0 +1,32 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.geuz.onelab" + android:versionCode="1" + android:versionName="1.0" > + + <uses-feature android:glEsVersion="0x00010000" android:required="true"></uses-feature> + <uses-sdk + android:minSdkVersion="14" + android:targetSdkVersion="15" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:theme="@style/AppTheme" android:logo="@drawable/ic_launcher"> + <activity + android:name=".MainActivity" + android:label="@string/title_activity_main" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + <intent-filter > + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + <data android:scheme="*" android:host="*" android:pathPattern=".*\\.geo" android:mimeType="text/plain" /> + </intent-filter> + </activity> + </application> + +</manifest> \ No newline at end of file diff --git a/contrib/mobile/Android/res/drawable-hdpi/ic_action_search.png b/contrib/mobile/Android/res/drawable-hdpi/ic_action_search.png new file mode 100644 index 0000000000000000000000000000000000000000..8a7da97f768c8a5bbd9da5db77b18ae5ac546ad6 GIT binary patch literal 555 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4kiW$h8qca7Z?~A*pj^6T^Rm@;DWu&Co?cG zKJavL42fucdu`*ZO$j2$KQ4~+j}%j75p;BFj!t~r>g*gHeb-yS(fq=tT9d7;u?``@ z0u!4}M5Y8NdY<?!KX1eI^1{~^KVoC-Up#D=St`;b($D*2zrd652M$ctF?!RV7G*|? zaVgC{Yc~6AjU7LO%+fDad;5+j-`*Bzq7x{>-rT5j+J<4x_3Rj4h8x@V-ppyZ8(=i^ z$kh!J&Fl?siv#th7n*i0y7Ia-!JLI*-D^3%_UE5F7kMrXn(C!0)LG+rP_w{Vr0LHu zovoR(x{opyt}Kn!pX&8M_iKhpkqo=*VWk$H_QUUk9%nHeD4g>?X!+&L7+&v5DhUd{ zmqS92UR|+jRi;$MVGm7H9_H7F1)W4(A6oDoTKY|&<>%MPSH~Y4&Ogt4xFGiXcaA`j z)mO7tUwvfpj(L{f^5c&`eivDPH}8Ah{@ZWO_!*|9KFo?(eU<A5uc}aIhDq1kMjth1 z9+CdzzyI!2;OLNwoVNR}-XH6p@4sbVe`jXsI;vEy{4nUZXw#oxdS7$Qtmpb^c>8j! zyqdLZUH!CKK~^(;d@ld7J(|7$zIET_mn9VpJMQM~kh)g3o3+e&l8T_y2HOdzpEfim zZH!odo%>GE{<!s@fA%aAWLX%X@xg}wVbE{!raxScb*y|}*dG}j+O=`ro8Jr!3=E#G KelF{r5}E+QSot>q literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/drawable-hdpi/ic_launcher.png b/contrib/mobile/Android/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..13ba1383cfb684d42ad5e12bd49bfc09ae51e3b6 GIT binary patch literal 865 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4rT@hhA$5${$yZa_!;06;`$#97#JAt-@o6` z(4e58@a@~%w{LGhe}4Y*<=uDg?6`1Y!HE+y{`~p*^XKR9-`_uaboAW0IR_3jeE$6W z!Gi-=uB<q5V#2FeSFc@LbM$D}p+hade}Dh__4WJr_wU`?bLPy9XV1>wxUu2<`FY2V z^?dm7@ZrP5|Ni~`@#EvmmzS?zUG@0!@xzDPX3S`aiE;7pFfcPyk(L(Pu%ThbjEo5r z5^{1prcFx;54Vz#5D*gL;pAjnv7(@*B_bigK}AJk*RGn48_VkILhS9e=FG`ROLH+W zP>_=o;o;#}x2|OJ<fMv<0B>(2U0u1TD4WK{FefJ+QBgi-W~Pu3i|yO1LLa`G$H2hA zSQ6wH%;50sMjD8d<n8Xl(7`I}!N9=4S>O>_%)lU&2f~bJ*p9?8Ffg!}c>21sU*hIw z;8u8@88MxKf$^cIi(^Q|oVQoqi<le)SRC6P{Lc^LNNJGWzfA87yH<Yf&KfiGorh|7 zZeo&BxX%#e!2E>q0gH)49pjV+wiEUZf)^Mn*#wxR6xKI<W|C5P-*A~pN<sO-ng+HG zHVe%KjEk7hab`3`Gz2qADVROzX<+MMw@_Tb_=x!%cgBJ0dWJV*7aA7YGi~EKwvXwC z<^o2qc;+|47Z}#AXDZ{&Xt;Hqv6{ui;k|T&ER$5i7u^F@jJz9usU>V}V4G1Zy&=qj z`OQA&2+akIe)pNz2wz}W|DGv~Go#`5cgAcMlLPPB8$_9;1imOA*wet~@>jq>djVsj zJ=+=142L`Z3~4MT3K!2a{9=-t@NzjrEF-VS*W!kG4Qx+-c{;c|Fi-lcvp{bF<IOs$ z0MQE#CHDL)I5Qmf#WRGkm@K%kp5YUdRKUyW43Uhy8eg*;rYyLo&t$|T74RmUabp8p z$nR7Kl?9AX>tr8rXE^M=&rrc6b>T%h!?p&tl3%(FstXv`*6}ak&Tv?NpCzNo?{C?C zDTnQK*-C1R=DEQQH!JR5V6OP6wCLjbE8HDY3k1$9efsNWlX`;j*H;0-@5>)E9%9w$ zw&vKp-zHBo<iNUJZ4$p`KURJuS)lPR>&NT)YwZ=^F)aD#ED`r}^W)!4<pGufo8}wq RF)%PNc)I$ztaD0e0sv9vcOC!$ literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/drawable-hdpi/ic_list.png b/contrib/mobile/Android/res/drawable-hdpi/ic_list.png new file mode 100644 index 0000000000000000000000000000000000000000..0845ffb33f34db2c2e4501f38c5dad6088d53f95 GIT binary patch literal 464 zcmeAS@N?(olHy`uVBq!ia0y~yU@&K3V9@1YV_;z5n)Z1&0|Ns~v6E*A2L}g74M$1` z0|NtRfk$L91B1Xn5N0&7n(M&8z#v)T8c`CQpH@<ySd_|8US6)3nU`IhoLG>mmtT}V z`<;yx0|TS4r;B4qM&sLC_SqtiGHegh%^5fDFbdu0nB%gVWgVvzlO>;yl3CK^XFJv_ zA6cI;nc2B(%5<gaP6iXaf}$h3B3_+O+FY<?!>!aAsq?aySKm+i_r@U9<p7JZ%%W-A zwdXtv78TV0s9Lzd&L`_k@bVWY_Z*viMYHPDmadN2nB{(#nzx&VRis<6zBdVeyQV5a zH(EJIrSnSff%9b_cHCL;WZ&|?;hNJ|2kC_`jalclGiGYh&Ra3R?;W4`hyPsoj~@F_ zm!5*=xl1<g`YKy(dQUpc@W!z<$6jCYtTI}=(PQo+_3pBBYd`3e&f>fK`0B6uKO%}X zXaCOHc|>(ljPa9IQ%;8>o1JSXm4EX8gFlO9w><ST@i&cI;&EkT{*Mm+P?sLl=~~X8 z(?0l{)-CnBIQf34i_P)tS3Ii>))sa%&v~4G%VuuGBMI^U47(P1UtIf4>=Oe61B0il KpUXO@geCwyYRRbp literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/drawable-hdpi/ic_mesh.png b/contrib/mobile/Android/res/drawable-hdpi/ic_mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..2c927569920e18ae051265d2fb7187c682cd8cf5 GIT binary patch literal 760 zcmeAS@N?(olHy`uVBq!ia0y~yU@&B0U@+idV_;y|abVI;1_lO}VkgfK4h{~E8jh3> z1_lPs0*}aI1_ptDAk1iDHP?ZGfkCpwHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^# z_B$IX1_q{5PZ!6KjK;UOPG<!>${hc=-ZQ}bU94D$$a?AUppSVQul?rUAsjd{Xpd6R zmbDRISz|i4zhdr?7H`_u{Eo%(!YYlmQTl7+#b-M7c%D<4G<mayy+zBJGxg_cPCSxH zGxAq8YCd3^V75)6bxOm|peGL$6L>V3Y7flzTdQTnn!s{{Psho3m*2|!R~b*g>|F8k zNoYX+O8KjG%3SAI4!rxY_jX59RrKEl>$tNsqYCsGeyzT>t5ah|`IYaC4nmKd7~ZVP zd@r_W#Xa7Jt)Xvu1;wvQZe8yeZ!X~ab)MDAbt_-4?v~(dn9Hl?BOMr`&XiC(_g}rh zbfyIN$)1;8M6R;GvMvp6Hmp~4yORIvTTAC<rzuz3UqzRuPA;@vrJ5jP!6(BskC|Io z&V*a(*dKqd1G)>uZ!qog(3-K_ZGZWa8TSulO=7e?u=-T?@uCEyq)+|_tR9r^Ufq4d z=z*l*eg{?2BO)IxH!YjG@ombkt4&VoVH3-WT*4+PZ<-`Caq5$fH7f2Ys+LOHCj}!t z`%ZX4rEW}K^s1!lb57llo}I^;GWb7k>YY_)By7Dw^oZdD@dA;GE3dkuP6R#Re0q0p zS|tA+b~UZpN4ka0D*RX2Uv1XRQCq*E=D_8gGi;?^dlw2dTSzjn2QeH`sJfc@wQ8v@ zr{Ri!0pFLicsS+oG<<yZEv;iA!;R@m3nY^!|8m_Mb^AI;p%ufoWjq-zH`dgJuD`N+ zWxItmL-j6(740{q7?OLlvIL(qCoJ%8h&p0+`gp<OvstSIr*3}zPb~kI=8-;z9dkm0 zE#K|plws>*@VEXh(|t<lfuVu>&v;w$$y}SN(#*Mgm<}5@|7WnV-<Di^D6Eiyfq}u( L)z4*}Q$iB}jXXoX literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/drawable-hdpi/ic_settings.png b/contrib/mobile/Android/res/drawable-hdpi/ic_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..aced98ab0d9c88e34b584f2b91441190f7cbf521 GIT binary patch literal 1412 zcmeAS@N?(olHy`uVBq!ia0y~yU@&B0V9@7aV_;zLa!~rtz`(##?Bp53!NI{%!;#X# zz`(#+;1OBOz#w1&!i;&^0*VX_43Z_T5hcO-X(i=}MX3zs<>h*rdD+Fui3O>8`9<lo z-`PkpFt9Rux;TbpG;W<4-4PZla=hL+?!ZK)Gq+P_X=*+cndy@1rj#kJefC5<$6_AG z7C9zPCi$+WDuG=Wyg6@qrv$jQq^_vsG`V2l<63*d`&CNvts526>2<bmJ|Dbp{(Rg1 z{6B{u9k^G$w)EfgHG99`$~Is5MVO6oaYI-_$)_CFZ%py7H+Hf{Fl}K}7Ov#~Vc@+` zbJ7uu2QR0H=d$Lp%nB;G#>nk;E1s){foDxtHoF>=xY5=tN|F<8)K|Fo9u_Q(;gnzT z**Hf>`;x9v&HP&n*9G;v3;j6ku!o27O0%X}-^ylbMZ@s7T{R!M{8mm@;^;ZQ;d7?s z-)B7<)q+2yGBhPmUwy$K$HwRS;?Bg2`<C|<Np&)|Tun^yiWfY`w7Ic%VpY1)t>aTJ z?6rO^el}pYvhxf1uk$(tR!u9EG%FW<;TyugwA9Dc=b6Nu@a5M%8A=!2nw<1~)i1xK z-8<dV7go91&fDf+!)_xb$Thv;c!RE>Ri*{wohg^=rEc)?DCcwtPx{8ZwXoj$L%@>H z#RoQe%r)6E**{6;gOAtmho_FzHEoc3%hu*%CC~eZ#i#Si>SIC)S#x(q2gV0gD?fLT zvRad$Wd3SD@7B$X%v)cCq({v=pmbTiByx?}&5i3_G`_Bq7q!@zapP?_hfR3Ga*pUL ziCVs|*b@9YZ~T_7;EiC_@tYU<f=!HZe)<=E7CYsfHJLXU�c+uGzVTsh+W3NNiGm zV;sX3#aG8<j{Ux3*|v4hFYkR(AC^{KQT_IpnfuIrkNU9n{ui}<7@{ZLpWJr6m}gI* zgG*`U)gP75+TZ7WZIfWSsuIw?>UMU|H>t3G8|C-Y6+TT%oELLWa`SPOW73L^RdaVK z8{SI&@zvFB))iCLj+nDAZ?EQC-`;TY$hx^9x-H2sZl(xLJ;?BY`;@%%>OzJYo*vq- zoZd)U^EY#9AA7?w*O`TBxm4ku`6>);O!f?yy?g%3R!o@i!?b11<k-D0l-9gY^(%dT zVs(Pcg8iNj7QMXshIv|wwenY29R8<f$a%x##Lv?Y{0>Pb#wh#!o_u8O0X3&p0?oHM zR{nWXCHq~xbK`-u2hV!`ExMYlvw?TVYPsis9T!b?NT_l9UwLTZ^3?~<c|34GwKnI! z``+CtO3GLNT3UbH-*$@gRnF(jeO$YEIMeTDy7%w|*PpGN+5Kvb)LhnQ%jHF5w#A&9 zJhRNfLwTOckslffECrJSL~gsEcx}#b*{JS=XoB2_TCe-u2eK|{zqtB>F^=t;NRRhl z;kB>M3B_x3hhJIFweOy`YVKFH<i&?GW0_gjtvWAe>6_x(a#z$)CC$WPfqU&fmBy|$ zJsb9K(&;pRt#V<tUY|<9#8AOHyN&sloB2D}mQK>p`t!_l^DeVP*P}`U<T@vZHuJBZ zeMSH3W!AQSbBCrUORu>LMCNN0ESY4ne%tNsc~{ohE!dY`wRXkrDfeYGov-8yx@?;j z;<~EWL{g9IxQNAX)x#Ot%_<&oS>-GfV_$uEbtlu{gT+zxwQnWgR*Jse^nyiBanA13 z2~r=*Ogm2>_$SmA`TU`@x0Rj~`@=bPOOD*IJ@Bb&(~WIC-;CrJ==cff>EA9sCZp)$ zm!5Nm&+Lxw^+yTzXWC6Njbk#eE^?k5BPpI;5_ybec73nMf_vE!rrJ9e+>5tWI~LLX zaME6>yRR-~dn{1ee8s!%&KmzB$>Q+6GXj!sdak(km#v0JX07(C#~WrA$Qp3{Shnr6 a{r<^J$AW!7?qFbGVDNPHb6Mw<&;$T-7kZ%p literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/drawable-ldpi/ic_launcher.png b/contrib/mobile/Android/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..09e5479ac7176a8f71b9337c950a52db986e0179 GIT binary patch literal 384 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F<YIY)RhkE)4%caKYZ?lNlHo zI14-?iy0V%3PG6h^PQ?b1_lQ95>H=O_DkH{3<AP``#(uDFfj6Zx;TbZ%y~Q0TIjF> z538%%cQ?D8L3?XDd|5nhFm7ASm{}fUDPa89*!=uyRX4@7k2QyL89P6k?szP;j<xE+ zrUUJ@4?+?}J#KF0m(g0o^giV+^JA{n3;{RU+eE_{7dibtu;P$bK&re%$c)_%lWQ+T zB;I3E`{wA}YRNt07W-7uXW9>v<U>MctZrCc8xWB=k16&|a}!sw$crp_4eg%z2O_^6 z0u$dbEx*NXuhkR%K<Jy}vO_ai^-|?!LL}B7P<`7xmn&Ix$Cla&Av>b)@6V0?B$s}E zEz6&k`5Wi+tzDWa`OG0CazWXH_mURX*91BuQ}1VG=&nkgaX7K@9`o{y*DQj9i$1gK hv2xqmKdOJqn5@^|xafn-76t|e22WQ%mvv4FO#m(cll=ey literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/drawable-mdpi/ic_action_search.png b/contrib/mobile/Android/res/drawable-mdpi/ic_action_search.png new file mode 100644 index 0000000000000000000000000000000000000000..134d5490bd3310559cc944d44d24857eef29f2a1 GIT binary patch literal 3030 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;|vT8oCO|{#S9GGLLkg|>2BR0 z1_mzwOlRkSfQ<Z-{NjxK0tHWJXN7{I{ItxRR0f8MTXTccLxNw5*?zzG#mT#)VTyNt zkSK>jkW+Vq$V4?QMNR>)4#kBxMFS5Cy1KGRpIFer+}GF8BO0i~)5Udz{fXkDzUIXp zU8jCOtX`abZO`{-Xa8-zZufl6=ee8DvmfB#ndV^}XxhND(n(J6LG$q=#~wb>b7<sJ zDPR!b*qowR{8yQg;YXc~jkeMO_I(VD6_>d=7!LT(K42iz{-6Jq)65vgh8D&HB@->Y zIT}P59IE=9mN7WEF*eMdp%%=rfQ2F9baK*Th5%iL1oir7ml+!7{+L<K$Phh6QIv7P zL<R-n)D9Ph3~Pop=fk>O86pfAMAE#ESTfwuWiapzPxD~du$|$+IRWlX3>-WR27w)| znhY$}3<)Qcl`9xpW-^GleG0evsJ%|$xfTOM#mr4MJ5?-Q8>2aN3)#cN_2e|pd5UX` zm?bhL&T`N@R5?@9sL_P~!RIp!3=1ZT3O;E5{I}v9-@0?>%=)(R#p}M>&-Py_De3XQ zr{`A}I503gEUCNrPe*^VRD(5JL+-yts_$4b;<y)-e(z4(#P6_`VZqB=;hzgYVdJ`R z!p@sFpFVkV!|RAsbmFP-+JEVX;tz!X&G}hp^XL252m2nWG#bS=y0iRvaOlhzpQSSA zCvmnU-FepU{%1S)|39*qm5z8O?TpY8c^oKI*yl2<=d;mLrB0_wnnzVH{ZDyxU*|Wo z-F;Jr4Ow=K)f07B#3nO;^Hvv#C^_)xI|IX~-T4QvXmBt$WHdiKU;h8S{a^P5stgTj zo|6h07~))1^g>Q;wm;6nz~Hi=QEP*v^p}GYItSQf4zk`k$o(h5ti?&?$RQ^IC$5wR znW6;EHBC+$ZD%*gY9;7jaga4R5SY<6xqwgaQ0NXm+XDVyi5&9|YV2v`WN|#fA)Kgq ztAjDAD?+)CLwsiI55<EXEJEEX3MV^60+qZcntB)pb%iK|ddPmVEn>24k8#^I(fR~~ zQPZEcJ?@568aD;nUg6p5ymN)QREygp?h7d;hO_#`7R<g-v_;Cc$86#A3#&8uZ}r<b zA2&GgLW14+NRENtvBORqEp#|1C!gM^w1#K(F{uq<YnXR;eoa2Vv7AMy(e(hQ8B4j7 zLZY0bM}$v=-wlry3Nk7tg10!$Ihk7m52-6nUg5n(ZI|HBBN9nQhV2m^I?C6C`i1oc zsym#In5zhNIvc6)oWSI{aY@J}p-XO;@`99K>a3h?;vuCx`Q)vX>`m;JQ*;!xPqaRn z`{eKw<0sNj6hB3C%}sJBT=FCMkw(y|EHBBY0#8kzvZc;2atvKOE9mZug&~5b{ZUS9 z7j6q$AK1P^*rarp<=JL2Pw%B`7frn^l_8$-J#+nwl3jv#r^@+FzYu=u^h@^_(_b)u zDd*vB6Ky`;k**;*TY_C8U9wza{S2RFl9#(BkB1nT8@`_Ld?x?Q{Ll!kZCW*=6HjqX z^_r?SRa#3wWaX-5tM0Ah4*eW@I;4MPTyX6=w@~BY$16FnOj{kgYHq;mVCmrWmDVfT zSEaAW53yfT7x}l7E%LC>VSnc(feSXqKi+dpfje1pbA^s#Ht*`T(nixGY8%hqtSQsl zJ>#$J?rz&vD;HWi8+#dtZw~rACC#4w@r=SBb4vU;pKC0i{<*H}p2&O6N1D>hOni14 zrp9Einl^n}#A=V#fveqL?=@TZcKO_8dtG-&{%+)RJnp3)qwb#Ge~xwT^WdAocb9W5 z7xT5X`npbURrXTpg}YtK_vbBtH)GzuxQ2N?`OEKB?tT7CrdI!N$lu&w%fGtwM6hk< zQDM8yb56qMsA*xojjaCh+aCj+V-GtxFHM}9IQ?PE#GMyy7GHJib>r{JJQnj<<#Fz@ z++&N?*whr&ynSE!zMB=~yK|Z5GHV}epW|oGoLzMG+Dy~gwuaY@p3i<h`}*wr+Y_QH zqI9;c*tR3pbJLTkWs&c;?a6D6vW#3B5gHY{*=_CIwW`;4uid>|aQRNZ$$qQnT}wZ_ z;p4WG+g5Iu-0<`U+wFDRa<|ncrYDJ~Z$G;3@Vm)-C)e((?fq-Z&f9*IZ?$ZcY+dn| zA`z=Ft9!G~&3R{Ed-Th+m-^`u=LOE+Fn+vE__XGc%(=m{FT1CUr|&Fo{@l^s>D_c% zZ@Qh{Z0TcnPwai-Rr0kk_F>hfuXAT_o_*-;ireeonZ3(=*M4XI8I$>%^CFFlFC0GM z{2=h@MSJe~Qw_53uc`BQ_HRtz`dnE*S$|^q+Upy(FD+m7J@LJ`-8Z|U`H$@$+nC=o zx)&LL#{9tc6WdSwAI_f_-+JG<Uip8@|Em8N8J0JwGNv<kHaa#&GyVQiRin7S&)({G z>bFfd-#Ydz*y$+h*x$6a>FL3>iWw)~OjxV<{rQY@6VGMxwFcC^xORa(@mXT`;W{4m z*7nx$Hv7JUjtHrXhSN>UFWzx3zVGtOWtz*q+3AM<mg{xBOttJ*>1Em6GT&vg%l?>N zTI89l5pyFvbG&6N^|aQR<>l<V|L5)J_D6FcaX+pWpP_#uwxDw1xkF!Cmy4~`6VkDo z=HS!eXEEi2qkz^5u^!b=!sV)cT$P7p52Y*VUo^Yeal<)AOV00;hn8>Eq&E}ym{zJB zHD0RobZ3kD$_aaXczy29wwfn4t4tx+$kuAFVe_Pk6AGPHDf&*{mi{XJSz6iYHL0ze z{vFNh-mWh<mHlM)<_T+9BXzm9IW2n;5~Xoni+xjiYIxfIvz@0br>&l+efI5{&8Kcp zFrV{&{{Oc^hlCzZ+P1XKJ6u;b;@RFcS(ck@3M+4OJr-rvZVO{uW3!`cn^x{s|J859 zr?0Eqt5)Tk-57W9RMWw&jM=ZbL%E)|*1o=T{cWs&gns1xt%<+d=1SX%c6O~3xh+0j zwEl+1or<T@?fIwn&%85b%gWV9cBY(9yOj3w**)EP(R|ZZO@B6>FOT=;tu4Iw!?wKr z`pxyW{`9jNw|6&hbKbdlzs-(4smo8EJ8NwpvLxh7$gdEycbD#NO}zdi@8Ub@>OJ2~ z-dw#Mz32O1yOaBFhcbrxUQN52`rGsO=I{3FI#<2?G3|G5>{`Fv!nennFERgRSLWMx zedm>{vX^W_g8Hv%zjo(4F2C>J-1p_Wyk@+iy>pH|QZ8_*eDd-;=l$<;yjHi$daBnv zWWOw5CYvs+pXD^`(=4~y!LxoxCq?h_KVx_C+N*n2f81}&^UpD{iLCVc9C9-A*2|{L zlhZ$)@0mMwZf%|3&pQdX7j3J4o_y|p7JvTxT>>Q!FS-8jer~<T`drMX9VMSO-F_+@ zz9W3rdaL-{S0%4({!PB@e|-0x-Luy1jLF{lu4?br>a_1KrRSNSyZdEt<wvpq*RIa9 zw7t9cb5;KLqu;;Y7rR?mr2hBZ>D@QW)!(h%<G&~Vi^E&To6dLJui8idyL03Ho%*Z; z<qJMvyyO0zt+o05zlmS_`JGw&XZD|N<86CA&%(~q@{xVf-<N-uJD*QEuQpHo-=cq~ z*NKbi*ZsKq`ue$xGcGQi{%QK;{kb(u|Gql#T5|pEV~38(?K@dvY#8???DyM)<#)<u z-!Hz;@BgGmp<d&E#?OskgD))qJy~+{<o_(pGd}-GHrBljYJ4Vp1o<*BRH-sBG&D0X z{QS?r(D0Ihq11qZ;Z*_ygVhWM2J!q!@kiYl7#Iu!d_r9RlL-9Q?{HvXU=Sz?@(X6* zl~OZy@J%aj=$*A}^MNxLXRVE6U|?A3>EaloaXvX=fmDFQ)2uuH>th)@&wu-O{@#E8 zi7cP$wG1-;`Zs)@dEm_-_X5Us?-M?$$2j~`jJRvRqv1c3LFqjPy#R(~->eU?sx9Dr z5zi3({$bjO8s^>a#1Ad}?_js_cT>U3U+N0a<6SsB{@TYC{`)U4+~V=>|Nr{K|NhT! z5HQp>PFV5(zp!b*tH3D?jrZzJRL{Ks|G(TpaO3a)_ZfUSXRYLU#>r#C#Gtam_UixU Snym~B3=E#GelF{r5}E+zcf7>_ literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/drawable-mdpi/ic_launcher.png b/contrib/mobile/Android/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..286d27e00068fb04f4dd541a4daa9b5a28cebd99 GIT binary patch literal 614 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4rT@hhPm4t-!L#Ru%tWsIx;Y9?C1WI$jZRL z@H4<C#PvTIFfcIOzkk1>p+P}G;oG;jZ{Oa2{`~yq%e(K~*>T~*f)giZ{Q2|q=g-gI zzrTO<=;*m~a}FG6`26|#g9it$Tv>7A#DrI`u3o#g=IGI`Lx);^|Nj2<>+ARL@87$( z=ggTI&z_yVabv^z^Ye}!>-q5E;lqcA|NZ;><HyIBFE3xcy6W-c<A)Eo&6v>;6XW9H zVPIyaA}uYnVMD`=85t8MB;@3HOq-Sx9&RNeAs{5g!^z3EVnsnqOGH9~gNlm8u3a@7 zH<s1ah1lC`&6$&tmgZt$pdcqF!o$O{Ze7Xb$w?Iz0p8w5y1H^vQ8tZ@VNOmuqN04v z%uFF67TdR1g+6>WkAZ=Ku_VYZn8D%MjWiG^$=lt9p@UV{gMop8v%n*=n1Mkk7lauT z_dhjeU|?V`@$_|Nzr@YWAjWhswKSiBf#I5`i(^Q|oTHaLg$@}AIA1(*^zV5e!BY)) zgQ^1<-u}P+(qf;@6nkcek1XN`m<w3M4+!57k6{qKAsWMwpWt7>Si@x9#Jzy^8mqVi z{~9j6297nHdJJr9IP@6!&T#87u%6-4W8gi*sn@_WLokNH(m*U`!Fy%{p%{fPf+twT zJ8T(^4zhZjXVBfj@LF>Li}(Ut_8kwH_J}hGx~y-|*wOGx^#Zq^LN)IcZ^pao4m$-V ze0_T-!sF2{5s9Nx3mN)%3jW@r=D~dCi0!9W;g8rX8|UtldU$pJeOW0}-j_T6cRprd PU|{fc^>bP0l+XkKUV{iJ literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/drawable-mdpi/model.png b/contrib/mobile/Android/res/drawable-mdpi/model.png new file mode 100644 index 0000000000000000000000000000000000000000..3a71677c81cae0c5bad62b5baa29b1c6001982e9 GIT binary patch literal 1116 zcmeAS@N?(olHy`uVBq!ia0y~yU<d$V4mJh`hCabhYZ(|A*pj^6T^Rm@;DWu&Co?cG za29w(7Beu2ECpf4A62<33=9nHC7!;n>~}Z?Mdej5=*_ofU|@df>EaktaqI1^v-#4l z5^Nuy&%9Y<k=r%dNk~JJl|{?d$;(G$@0Tmi-A7oTFrQ*PDgQfP;U7=V^G6;WCxyZt z9yLv<Vo2iN%B0G^>R48kl4;)^vzs*)aePaHZsr{|>z#X}w*L6WJ<0Y}-|tFRGc27F z<fVyBSY4_Ju{-hRP0s%Z4<1NgyA|%5GABjofT7^a`@iShR@u(L!f?$cW$KeG0hX^t zJ8RzW<TaRndah!n+<|D7w{`0jm9&*MxqOP+7!gyg$8;ve=<&5%r&Z3&TrqWZ@zC2A zwRUxJaq(Bb8vgeNhfY8LEI(-v%K^Cz(+MmE*P^P$4otTdPq3PsW;F9p$CKawD;CHy zlroqzT$x+Uzis<=bD>U`4Lf&c3U?lHSbfzhv8S^0i8jMMmV!?P(E;wvK5CPvFFqtZ zF?Z7boZQ@4-RY-i`&aB{-oX68u0fPx|NE~O3?~_@+-JUUe>4BY7(Mgco}U&<d!kkL zYl?7vpTBYWx9IHi%sV_TX^U{l?rhCfSNm97-|{5=;ZK*8iBGP#Iw@9Mv&`BWwK{68 zp1;3;JhMU6+OYNCeORA;{%LZuc;Sb4Y>pqU{`vFA&s=}WUcQj~5)B0vd<VAQm6Kzb zQRc6p6zG4)zWeASFa4aSx1<uR=BhQ6D?9z&8vgB2E^k3a#Sf8_3j->8gI1OVGxro1 zCi}Vb=zqVo-Y}PU!V{M($KsiL@=X?L<!3j1)Gn~F*|vN4?uCrU;t%oIZChBX_hKo- zUbFCo_#+?oF@351-@UxnU;W!*wpSka5B29>wK*?+h2in-t{08Aq6xd}eKMFN_`V)h zWGLs~HUI5$_cCYJb*^ie)xU`Kz4tqELzCBF-_wqzXP2-^T>kazm#!e^e@~NHXVd(% z8w^9VL=`J-7xACVXfU*VUe_&Q_x$(27B&gzl_6206YZU9FEISL^1ardxo5ljKf(Y1 zH2<v-cYQLs#OiHk!~gvpc^xPC1rP3<?4xFX{%O(iU8WAVS9Y$t`s!_nmZ?Y_`y?Ai zg{fXke=S?K?A?{Dt#_C2%u|~zIe+HNolFTje{LN*bjbhizNx?a-4=iRd*Va~>jbV= z3x)@a44*Z<|9x7i=&)tD_(b-3&vSKjby+7*o_z1X0f+s??{;kcrqVE-agT4&8w2eR z0q59%?W=cm(R*v_!#Ahn5ATEBNgFFRt247S)Y#ecJ>WWdozGy0+R6FSy~muE22Gr| z_JDip=9|}h4doN&yVtlbVNJMb8J=r4yS`LwhqCYkXMX;f(#dL`ecdOx8Tux_5f)@# zu(kZeAGwCMjx|=#U!6@W-WjyA<gcVOaxM$<+IrP~&()OEhUN9=85kHCJYD@<);T3K F0RSep{C@xd literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/drawable-mdpi/param.png b/contrib/mobile/Android/res/drawable-mdpi/param.png new file mode 100644 index 0000000000000000000000000000000000000000..0103c21fe2a6bbcd3e59fa6f3ca9503cfc367e60 GIT binary patch literal 3371 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 literal 0 HcmV?d00001 diff --git a/contrib/mobile/Android/res/layout/list_header.xml b/contrib/mobile/Android/res/layout/list_header.xml new file mode 100644 index 0000000000..bf26b6dcbd --- /dev/null +++ b/contrib/mobile/Android/res/layout/list_header.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/list_header_title" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingTop="2dip" + android:paddingBottom="2dip" + android:paddingLeft="5dip" + style="?android:attr/listSeparatorTextViewStyle" + > + + +</TextView> \ No newline at end of file diff --git a/contrib/mobile/Android/res/layout/model.xml b/contrib/mobile/Android/res/layout/model.xml new file mode 100644 index 0000000000..9301369f01 --- /dev/null +++ b/contrib/mobile/Android/res/layout/model.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" > + + <ImageView + android:id="@+id/icone" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="icone" + android:src="@drawable/ic_launcher" /> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:orientation="vertical" > + + <TextView + android:id="@+id/titre" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textColor="#ffffff" /> + + <TextView + android:id="@+id/description" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="#ffffff" /> + + </LinearLayout> + +</LinearLayout> \ No newline at end of file diff --git a/contrib/mobile/Android/res/raw/bh_pro b/contrib/mobile/Android/res/raw/bh_pro new file mode 100644 index 0000000000..1458d87c83 --- /dev/null +++ b/contrib/mobile/Android/res/raw/bh_pro @@ -0,0 +1,59 @@ +Function{ + // nu = 100. + 10. * exp ( 1.8 * b * b ) + // analytical + nu_1a[] = 100. + 10. * Exp[1.8*SquNorm[$1]] ; + dnudb2_1a[] = 18. * Exp[1.8*SquNorm[$1]] ; + h_1a[] = nu_1a[$1]*$1 ; + dhdb_1a[] = TensorDiag[1,1,1] * nu_1a[$1#1] + 2*dnudb2_1a[#1] * SquDyadicProduct[#1] ; + dhdb_1a_NL[] = 2*dnudb2_1a[$1] * SquDyadicProduct[$1] ; + + // interpolated + Mat1_h = { + 0.0000e+00, 5.5023e+00, 1.1018e+01, 1.6562e+01, 2.2149e+01, 2.7798e+01, 3.3528e+01, + 3.9363e+01, 4.5335e+01, 5.1479e+01, 5.7842e+01, 6.4481e+01, 7.1470e+01, 7.8906e+01, + 8.6910e+01, 9.5644e+01, 1.0532e+02, 1.1620e+02, 1.2868e+02, 1.4322e+02, 1.6050e+02, + 1.8139e+02, 2.0711e+02, 2.3932e+02, 2.8028e+02, 3.3314e+02, 4.0231e+02, 4.9395e+02, + 6.1678e+02, 7.8320e+02, 1.0110e+03, 1.3257e+03, 1.7645e+03, 2.3819e+03, 3.2578e+03, + 4.5110e+03, 6.3187e+03, 8.9478e+03, 1.2802e+04, 1.8500e+04, 2.6989e+04, 3.9739e+04, + 5.9047e+04, 8.8520e+04, 1.3388e+05, 2.0425e+05, 3.1434e+05, 4.8796e+05, 7.6403e+05 + } ; + Mat1_b = { + 0.0000e+00, 5.0000e-02, 1.0000e-01, 1.5000e-01, 2.0000e-01, 2.5000e-01, 3.0000e-01, + 3.5000e-01, 4.0000e-01, 4.5000e-01, 5.0000e-01, 5.5000e-01, 6.0000e-01, 6.5000e-01, + 7.0000e-01, 7.5000e-01, 8.0000e-01, 8.5000e-01, 9.0000e-01, 9.5000e-01, 1.0000e+00, + 1.0500e+00, 1.1000e+00, 1.1500e+00, 1.2000e+00, 1.2500e+00, 1.3000e+00, 1.3500e+00, + 1.4000e+00, 1.4500e+00, 1.5000e+00, 1.5500e+00, 1.6000e+00, 1.6500e+00, 1.7000e+00, + 1.7500e+00, 1.8000e+00, 1.8500e+00, 1.9000e+00, 1.9500e+00, 2.0000e+00, 2.0500e+00, + 2.1000e+00, 2.1500e+00, 2.2000e+00, 2.2500e+00, 2.3000e+00, 2.3500e+00, 2.4000e+00 + } ; + Mat1_b2 = { + 0.0000e+00, 2.5000e-03, 1.0000e-02, 2.2500e-02, 4.0000e-02, 6.2500e-02, 9.0000e-02, + 1.2250e-01, 1.6000e-01, 2.0250e-01, 2.5000e-01, 3.0250e-01, 3.6000e-01, 4.2250e-01, + 4.9000e-01, 5.6250e-01, 6.4000e-01, 7.2250e-01, 8.1000e-01, 9.0250e-01, 1.0000e+00, + 1.1025e+00, 1.2100e+00, 1.3225e+00, 1.4400e+00, 1.5625e+00, 1.6900e+00, 1.8225e+00, + 1.9600e+00, 2.1025e+00, 2.2500e+00, 2.4025e+00, 2.5600e+00, 2.7225e+00, 2.8900e+00, + 3.0625e+00, 3.2400e+00, 3.4225e+00, 3.6100e+00, 3.8025e+00, 4.0000e+00, 4.2025e+00, + 4.4100e+00, 4.6225e+00, 4.8400e+00, 5.0625e+00, 5.2900e+00, 5.5225e+00, 5.7600e+00 + } ; + Mat1_nu = { + 1.1005e+02, 1.1005e+02, 1.1018e+02, 1.1041e+02, 1.1075e+02, 1.1119e+02, 1.1176e+02, + 1.1247e+02, 1.1334e+02, 1.1440e+02, 1.1568e+02, 1.1724e+02, 1.1912e+02, 1.2139e+02, + 1.2416e+02, 1.2752e+02, 1.3165e+02, 1.3671e+02, 1.4297e+02, 1.5076e+02, 1.6050e+02, + 1.7275e+02, 1.8829e+02, 2.0810e+02, 2.3356e+02, 2.6651e+02, 3.0947e+02, 3.6589e+02, + 4.4056e+02, 5.4014e+02, 6.7397e+02, 8.5528e+02, 1.1028e+03, 1.4436e+03, 1.9164e+03, + 2.5777e+03, 3.5104e+03, 4.8366e+03, 6.7381e+03, 9.4870e+03, 1.3494e+04, 1.9385e+04, + 2.8118e+04, 4.1172e+04, 6.0854e+04, 9.0779e+04, 1.3667e+05, 2.0764e+05, 3.1835e+05 + } ; + + Mat1_nu_b2 = ListAlt[Mat1_b2, Mat1_nu] ; + nu_1[] = InterpolationLinear[$1]{List[Mat1_nu_b2]} ; + dnudb2_1[] = dInterpolationLinear[$1]{List[Mat1_nu_b2]} ; + h_1[] = nu_1[(SquNorm[$1])] * $1 ; + dhdb_1[] = TensorDiag[1,1,1] * nu_1[SquNorm[$1]#1] + 2*dnudb2_1[#1] * SquDyadicProduct[$1] ; +} + + + + + + diff --git a/contrib/mobile/Android/res/raw/machine_magstadyn_a_pro b/contrib/mobile/Android/res/raw/machine_magstadyn_a_pro new file mode 100644 index 0000000000..f58a22b84a --- /dev/null +++ b/contrib/mobile/Android/res/raw/machine_magstadyn_a_pro @@ -0,0 +1,938 @@ +Group { + DefineGroup[ DomainM, DomainB, DomainS ]; + DefineGroup[ DomainL, DomainNL, Dummy ]; + DefineGroup[ Rotor_Inds, Rotor_IndsP, Rotor_IndsN, Rotor_Magnets, Rotor_Bars ]; + DefineGroup[ Surf_bn0, Rotor_Bnd_MBaux] ; + DefineGroup[ Resistance_Cir, Inductance_Cir, Capacitance_Cir, DomainZt_Cir, DomainSource_Cir ]; +} + +Function{ + + DefineConstant[ Flag_Cir, Flag_NL, Flag_ParkTransformation ]; + DefineConstant[ Term_vxb ]; + DefineConstant[ AxialLength = {1, Visible 0}, + FillFactor_Winding = {1, Visible 0}, + Factor_R_3DEffects = {1, Visible 0}, + SymmetryFactor = {1, Visible 0} ]; + + Flag_Symmetry = (SymmetryFactor==1) ? 0 : 1 ; + + DefineConstant[ Nb_max_iter = {20, Visible 0}, + relaxation_factor = {1, Visible 0}, + stop_criterion = {1e-5, Visible 0}, + reltol = {1e-7, Visible 0}, + abstol = {1e-5, Visible 0} ]; + + DefineConstant[ II, VV, pA, pB, pC, Ie, ID, IQ, I0 ]; + DefineFunction[ br, js, Resistance, Inductance, Capacitance ]; + DefineFunction[ Theta_Park, Theta_Park_deg, RotorPosition, RotorPosition_deg ] ; + + + DefineConstant[ Flag_SrcType_Rotor = {0, Visible 0} ]; + + DefineConstant[ Clean_Results = { 1, Choices {0,1}, + Label "Remove previous result files", + Path "Input/1", Visible 1 } ] ; + + DefineConstant[ Flag_SaveAllSteps = {0, Label "Save all time steps", + Path "Input/0", Choices {0,1}} ]; + + DefineConstant[ my_output={"Output/40T_rotor", Visible 0}]; + +} + +Include "bh.pro"; // nonlinear BH caracteristic of magnetic material + +Group { + + Inds = Region[ {Stator_Inds, Rotor_Inds} ] ; + + DomainB = Region[ {Inds} ] ; + DomainM = Region[ {Rotor_Magnets} ] ; + + Stator = Region[{ StatorC, StatorCC }] ; + Rotor = Region[{ RotorC, RotorCC }] ; + + Rotor_Moving = Region[{ Rotor, Rotor_Air, Rotor_Airgap, Rotor_Inds, Rotor_Bnd_MBaux} ] ; // Use in ChangeOfCoordinates + + MB = MovingBand2D[ MovingBand_PhysicalNb, Stator_Bnd_MB, Rotor_Bnd_MB, SymmetryFactor] ; + Air = Region[{ Rotor_Air, Rotor_Airgap, Stator_Air, Stator_Airgap, MB } ] ; + Inds = Region[{ Rotor_Inds, Stator_Inds } ] ; + + DomainV = Region[{}]; // Speed considered either with term v/\b + If(Term_vxb) // or not dynamics in time domain + mechanics + DomainV = Region[{ RotorC }]; + EndIf + + DomainCC = Region[{ Air, Inds, StatorCC, RotorCC }]; + DomainC = Region[{ StatorC, RotorC }]; + Domain = Region[{ DomainCC, DomainC }] ; + + If(Flag_NL) + DomainNL = Region[ {Stator_Fe, Rotor_Fe } ]; + DomainL = Region[ {Domain,-DomainNL} ]; + EndIf + + DomainKin = #1234 ; // Dummy region number for mechanical equation + DomainDummy = #12345 ; // Dummy region number for mechanical equation +} + +Function { + mu0 = 4.e-7 * Pi ; + + sigma_al = 3.72e7 ; // conductivity of aluminum [S/m] + sigma_cu = 5.9e7 ; // conductivity of copper [S/m] + + nu [#{Air, Inds, Stator_Al, Rotor_Al, Stator_Cu, Rotor_Cu, Rotor_Magnets, Rotor_Bars}] = 1. / mu0 ; + + If(!Flag_NL) + nu [#{Stator_Fe, Rotor_Fe }] = 1 / (mur_fe * mu0) ; + EndIf + If(Flag_NL) + nu [#{Stator_Fe, Rotor_Fe }] = nu_1a[$1] ; + EndIf + dhdb_NL [ DomainNL ] = dhdb_1a_NL[$1]; + + sigma[#{Rotor_Fe}] = sigma_fe ; + sigma[#{Rotor_Al, Stator_Al}] = sigma_al ; + sigma[#{Rotor_Cu, Stator_Cu}] = sigma_cu ; + sigma[#{Inds}] = sigma_cu ; + + rho[] = 1/sigma[] ; + + Rb[] = Factor_R_3DEffects*AxialLength*FillFactor_Winding*NbWires[]^2/SurfCoil[]/sigma[] ; + Resistance[#{Stator_Inds, Rotor_Inds}] = Rb[] ; + + T = 1/Freq ; // Fundamental period in s + + Idir[#{Stator_IndsP, Rotor_IndsP}] = 1 ; + Idir[#{Stator_IndsN, Rotor_IndsN}] = -1 ; + + // Functions for Park transformation + Idq0[] = Vector[ ID, IQ, I0 ] ; + Pinv[] = Tensor[ Sin[Theta_Park[]], Cos[Theta_Park[]], 1, + Sin[Theta_Park[]-2*Pi/3], Cos[Theta_Park[]-2*Pi/3], 1, + Sin[Theta_Park[]+2*Pi/3], Cos[Theta_Park[]+2*Pi/3], 1 ]; + + P[] = 2/3 * Tensor[ Sin[Theta_Park[]], Sin[Theta_Park[]-2*Pi/3], Sin[Theta_Park[]+2*Pi/3], + Cos[Theta_Park[]], Cos[Theta_Park[]-2*Pi/3], Cos[Theta_Park[]+2*Pi/3], + 1/2, 1/2, 1/2 ] ; + + Iabc[] = Pinv[] * Idq0[] ; + Flux_dq0[] = P[] * Vector[#11, #22, #33] ; + + If(Flag_ParkTransformation) + II = 1 ; + IA[] = CompX[ Iabc[] ] ; + IB[] = CompY[ Iabc[] ] ; + IC[] = CompZ[ Iabc[] ] ; + EndIf + If(!Flag_ParkTransformation) + IA[] = F_Sin_wt_p[]{2*Pi*Freq, pA} ; + IB[] = F_Sin_wt_p[]{2*Pi*Freq, pB} ; + IC[] = F_Sin_wt_p[]{2*Pi*Freq, pC} ; + + js[PhaseA] = II * NbWires[]/SurfCoil[] * IA[] * Idir[] * Vector[0, 0, 1] ; + js[PhaseB] = II * NbWires[]/SurfCoil[] * IB[] * Idir[] * Vector[0, 0, 1] ; + js[PhaseC] = II * NbWires[]/SurfCoil[] * IC[] * Idir[] * Vector[0, 0, 1] ; + EndIf + + Velocity[] = wr*XYZ[]/\Vector[0,0,1] ; + + // Maxwell stress tensor + T_max[] = ( SquDyadicProduct[$1] - SquNorm[$1] * TensorDiag[0.5, 0.5, 0.5] ) / mu0 ; + T_max_cplx[] = ( TensorV[CompX[$1]*Conj[$1],CompY[$1]*Conj[$1],CompZ[$1]*Conj[$1]] - $1*Conj[$1] * TensorDiag[0.5, 0.5, 0.5] ) / mu0 ; // Check if valid + + + AngularPosition[] = (Atan2[$Y,$X]#7 >= 0.)? #7 : #7+2*Pi ; + + RotatePZ[] = Rotate[ Vector[$X,$Y,$Z], 0, 0, $1 ] ;//Watch out: Do not use XYZ[]! + + // Kinematics + Inertia = 8.3e-3 ; //87 + Friction[] = 0 ; + + Fmag[] = #55 ; // Computed in postprocessing +} + +//------------------------------------------------------------------------------------- + +Jacobian { + { Name Vol; Case { { Region All ; Jacobian Vol; } } } +} + +Integration { + { Name I1 ; Case { + { Type Gauss ; + Case { + { GeoElement Triangle ; NumberOfPoints 6 ; } + { GeoElement Quadrangle ; NumberOfPoints 4 ; } + { GeoElement Line ; NumberOfPoints 13 ; } + } + } + } + } +} + +//------------------------------------------------------------------------------------- + +Constraint { + + { Name MVP_2D ; + Case { + { Region Surf_Inf ; Type Assign; Value 0. ; } + { Region Surf_bn0 ; Type Assign; Value 0. ; } + + If(Flag_Symmetry) + { Region Surf_cutA1; SubRegion Region[{Surf_Inf,Surf_bn0}]; Type Link; + RegionRef Surf_cutA0; SubRegionRef Region[{Surf_Inf,Surf_bn0}]; + Coefficient (NbrPoles%2)?-1:1 ; Function RotatePZ[-NbrPoles*2*Pi/NbrPolesTot]; } + { Region Surf_cutA1; Type Link; RegionRef Surf_cutA0; + Coefficient (NbrPoles%2)?-1:1 ; Function RotatePZ[-NbrPoles*2*Pi/NbrPolesTot]; } + + //For the moving band + For k In {1:SymmetryFactor-1} + { Region Rotor_Bnd_MB~{k+1} ; SubRegion Rotor_Bnd_MB~{(k!=SymmetryFactor-1)?k+2:1}; Type Link; + RegionRef Rotor_Bnd_MB_1; SubRegionRef Rotor_Bnd_MB_2; + Coefficient ((NbrPoles%2)?-1:1)^(k); Function RotatePZ[-k*NbrPoles*2*Pi/NbrPolesTot]; } + EndFor + + EndIf + } + } + + { Name Current_2D ; + Case { + If(Flag_SrcType_Stator==1) + { Region PhaseA ; Value II*Idir[] ; TimeFunction IA[]; } + { Region PhaseB ; Value II*Idir[] ; TimeFunction IB[]; } + { Region PhaseC ; Value II*Idir[] ; TimeFunction IC[]; } + EndIf + If(Flag_SrcType_Rotor==1) + { Region Rotor_Inds ; Value Ie*Idir[] ; } + EndIf + } + } + + { Name Voltage_2D ; + Case { + { Region RotorC ; Value 0. ; } // Not needed if Global equation not in formulation + { Region StatorC ; Value 0. ; } // Not needed if Global equation not in formulation + } + } + + { Name Current_Cir ; + Case { + If(Flag_Cir && Flag_SrcType_Stator==1) + { Region Input1 ; Value II ; TimeFunction IA[]; } + { Region Input2 ; Value II ; TimeFunction IB[]; } + { Region Input3 ; Value II ; TimeFunction IC[]; } + EndIf + } + } + + { Name Voltage_Cir ; // Example induction machine + Case { + If(Flag_Cir && Flag_SrcType_Stator==2 && !Flag_NL) + { Region Input1 ; Value VV ; TimeFunction IA[]; } + { Region Input2 ; Value VV ; TimeFunction IB[]; } + { Region Input3 ; Value VV ; TimeFunction IC[]; } + EndIf + If(Flag_Cir && Flag_SrcType_Stator==2 && Flag_NL) + { Region Input1 ; Value VV ; TimeFunction IA[]*Frelax[]; } + { Region Input2 ; Value VV ; TimeFunction IB[]*Frelax[]; } + { Region Input3 ; Value VV ; TimeFunction IC[]*Frelax[]; } + EndIf + } + } + + + //Kinetics + { Name CurrentPosition ; + Case { + { Region DomainKin ; Type Init ; Value 0.#66 ; } + } + } + + { Name CurrentVelocity ; + Case { + { Region DomainKin ; Type Init ; Value wr ; } // wr in [0,1200] rad/s + } + } + +} + +//----------------------------------------------------------------------------------------------- + +FunctionSpace { + + { Name Hcurl_a_2D ; Type Form1P ; + BasisFunction { + { Name se1 ; NameOfCoef ae1 ; Function BF_PerpendicularEdge ; + Support Region[{ Domain, Rotor_Bnd_MBaux }] ; Entity NodesOf [ All ] ; } + } + Constraint { + { NameOfCoef ae1 ; EntityType NodesOf ; NameOfConstraint MVP_2D ; } + } + } + + // Gradient of Electric scalar potential (2D) + { Name Hregion_u_Mag_2D ; Type Form1P ; + BasisFunction { + { Name sr ; NameOfCoef ur ; Function BF_RegionZ ; + Support DomainC ; Entity DomainC ; } + } + GlobalQuantity { + { Name U ; Type AliasOf ; NameOfCoef ur ; } + { Name I ; Type AssociatedWith ; NameOfCoef ur ; } + } + Constraint { + { NameOfCoef U ; EntityType GroupsOfNodesOf ; NameOfConstraint Voltage_2D ; } + { NameOfCoef I ; EntityType GroupsOfNodesOf ; NameOfConstraint Current_2D ; } + } + } + + { Name Hregion_i_Mag_2D ; Type Vector ; + BasisFunction { + { Name sr ; NameOfCoef ir ; Function BF_RegionZ ; + Support DomainB ; Entity DomainB ; } + } + GlobalQuantity { + { Name Ib ; Type AliasOf ; NameOfCoef ir ; } + { Name Ub ; Type AssociatedWith ; NameOfCoef ir ; } + } + Constraint { + { NameOfCoef Ub ; EntityType Region ; NameOfConstraint Voltage_2D ; } + { NameOfCoef Ib ; EntityType Region ; NameOfConstraint Current_2D ; } + } + } + + { Name Hregion_Z ; Type Scalar ; // Circuit equations + BasisFunction { + { Name sr ; NameOfCoef ir ; Function BF_Region ; + Support DomainZt_Cir ; Entity DomainZt_Cir ; } + } + GlobalQuantity { + { Name Iz ; Type AliasOf ; NameOfCoef ir ; } + { Name Uz ; Type AssociatedWith ; NameOfCoef ir ; } + } + Constraint { + { NameOfCoef Uz ; EntityType Region ; NameOfConstraint Voltage_Cir ; } + { NameOfCoef Iz ; EntityType Region ; NameOfConstraint Current_Cir ; } + } + } + + // For use in Mechanical equation + { Name Position ; Type Scalar ; + BasisFunction { + { Name sr ; NameOfCoef ir ; Function BF_Region ; + Support DomainKin ; Entity DomainKin ; } + } + GlobalQuantity { + { Name P ; Type AliasOf ; NameOfCoef ir ; } + } + Constraint { + { NameOfCoef P ; EntityType Region ; NameOfConstraint CurrentPosition ; } + } + } + + + { Name Velocity ; Type Scalar ; + BasisFunction { + { Name sr ; NameOfCoef ir ; Function BF_Region ; + Support DomainKin ; Entity DomainKin ; } } + GlobalQuantity { + { Name V ; Type AliasOf ; NameOfCoef ir ; } + } + Constraint { + { NameOfCoef V ; EntityType Region ; NameOfConstraint CurrentVelocity ; } + } + } + +} + +//----------------------------------------------------------------------------------------------- + +Formulation { + + { Name MagSta_a_2D ; Type FemEquation ; + Quantity { + { Name a ; Type Local ; NameOfSpace Hcurl_a_2D ; } + + { Name ir ; Type Local ; NameOfSpace Hregion_i_Mag_2D ; } + { Name Ub ; Type Global ; NameOfSpace Hregion_i_Mag_2D [Ub] ; } + { Name Ib ; Type Global ; NameOfSpace Hregion_i_Mag_2D [Ib] ; } + + { Name Uz ; Type Global ; NameOfSpace Hregion_Z [Uz] ; } + { Name Iz ; Type Global ; NameOfSpace Hregion_Z [Iz] ; } + } + + Equation { + Galerkin { [ nu[{d a}] * Dof{d a} , {d a} ] ; + In Domain ; Jacobian Vol ; Integration I1 ; } + Galerkin { JacNL [ dhdb_NL[{d a}] * Dof{d a} , {d a} ] ; + In DomainNL ; Jacobian Vol ; Integration I1 ; } + + Galerkin { [ 0*Dof{d a} , {d a} ] ; // DO NOT REMOVE!!! - Keeping track of Dofs in auxiliary line of MB if Symmetry=1 + In Rotor_Bnd_MBaux; Jacobian Vol; Integration I1; } + + Galerkin { [ -nu[] * br[] , {d a} ] ; + In DomainM ; Jacobian Vol ; Integration I1 ; } + + Galerkin { [ -js[] , {a} ] ; + In DomainS ; Jacobian Vol ; Integration I1 ; } + + Galerkin { [ -NbWires[]/SurfCoil[] * Dof{ir} , {a} ] ; + In DomainB ; Jacobian Vol ; Integration I1 ; } + Galerkin { DtDof [ AxialLength * NbWires[]/SurfCoil[] * Dof{a} , {ir} ] ; + In DomainB ; Jacobian Vol ; Integration I1 ; } + GlobalTerm { [ Dof{Ub}/SymmetryFactor, {Ib} ] ; In DomainB ; } + Galerkin { [ Rb[]/SurfCoil[]* Dof{ir} , {ir} ] ; + In DomainB ; Jacobian Vol ; Integration I1 ; } + + // GlobalTerm { [ Resistance[] * Dof{Ib} , {Ib} ] ; In DomainB ; } + // The above term can replace: + // Galerkin{ [ NbWires[]/SurfCoil[] / sigma[] * NbWires[]/SurfCoil[] * Dof{ir}, {ir} ] + // if we have an estimation of the resistance of DomainB, via e.g. measurements + + If(Flag_Cir) + GlobalTerm { NeverDt[ Dof{Uz} , {Iz} ] ; In Resistance_Cir ; } + GlobalTerm { NeverDt[ Resistance[] * Dof{Iz} , {Iz} ] ; In Resistance_Cir ; } + + GlobalTerm { [ 0. * Dof{Iz} , {Iz} ] ; In DomainSource_Cir ; } + GlobalTerm { [ 0. * Dof{Uz} , {Iz} ] ; In DomainZt_Cir ; } + + GlobalEquation { + Type Network ; NameOfConstraint ElectricalCircuit ; + { Node {Iz}; Loop {Uz}; Equation {Uz}; In DomainZt_Cir ; } + { Node {Ib}; Loop {Ub}; Equation {Ub}; In DomainB ; } + } + EndIf + } + } + + { Name MagDyn_a_2D ; Type FemEquation ; + Quantity { + { Name a ; Type Local ; NameOfSpace Hcurl_a_2D ; } + { Name ur ; Type Local ; NameOfSpace Hregion_u_Mag_2D ; } + { Name I ; Type Global ; NameOfSpace Hregion_u_Mag_2D [I] ; } + { Name U ; Type Global ; NameOfSpace Hregion_u_Mag_2D [U] ; } + + { Name ir ; Type Local ; NameOfSpace Hregion_i_Mag_2D ; } + { Name Ub ; Type Global ; NameOfSpace Hregion_i_Mag_2D [Ub] ; } + { Name Ib ; Type Global ; NameOfSpace Hregion_i_Mag_2D [Ib] ; } + + { Name Uz ; Type Global ; NameOfSpace Hregion_Z [Uz] ; } + { Name Iz ; Type Global ; NameOfSpace Hregion_Z [Iz] ; } + } + Equation { + Galerkin { [ nu[{d a}] * Dof{d a} , {d a} ] ; + In Domain ; Jacobian Vol ; Integration I1 ; } + Galerkin { JacNL [ dhdb_NL[{d a}] * Dof{d a} , {d a} ] ; + In DomainNL ; Jacobian Vol ; Integration I1 ; } + + Galerkin { [ 0*Dof{d a} , {d a} ] ; // DO NOT REMOVE!!! - Keeping track of Dofs in auxiliary line of MB if Symmetry=1 + In Rotor_Bnd_MBaux; Jacobian Vol; Integration I1; } + + Galerkin { [ -nu[] * br[] , {d a} ] ; + In DomainM ; Jacobian Vol ; Integration I1 ; } + + Galerkin { DtDof[ sigma[] * Dof{a} , {a} ] ; + In DomainC ; Jacobian Vol ; Integration I1 ; } + Galerkin { [ sigma[] * Dof{ur}, {a} ] ; + In DomainC ; Jacobian Vol ; Integration I1 ; } + + Galerkin { [ -sigma[] * (Velocity[] *^ Dof{d a}) , {a} ] ; + In DomainV ; Jacobian Vol ; Integration I1 ; } + + Galerkin { [ -js[] , {a} ] ; + In DomainS ; Jacobian Vol ; Integration I1 ; } + + Galerkin { DtDof[ sigma[] * Dof{a} , {ur} ] ; + In DomainC ; Jacobian Vol ; Integration I1 ; } + Galerkin { [ sigma[] * Dof{ur} , {ur} ] ; + In DomainC ; Jacobian Vol ; Integration I1 ; } + GlobalTerm { [ Dof{I} , {U} ] ; In DomainC ; } + + Galerkin { [ -NbWires[]/SurfCoil[] * Dof{ir} , {a} ] ; + In DomainB ; Jacobian Vol ; Integration I1 ; } + Galerkin { DtDof [ AxialLength * NbWires[]/SurfCoil[] * Dof{a} , {ir} ] ; + In DomainB ; Jacobian Vol ; Integration I1 ; } + GlobalTerm { [ Dof{Ub}/SymmetryFactor , {Ib} ] ; In DomainB ; } + Galerkin { [ Rb[]/SurfCoil[]* Dof{ir} , {ir} ] ; + In DomainB ; Jacobian Vol ; Integration I1 ; } // Resistance term + + // GlobalTerm { [ Resistance[] * Dof{Ib} , {Ib} ] ; In DomainB ; } + // The above term can replace the resistance term: + // if we have an estimation of the resistance of DomainB, via e.g. measurements + // which is better to account for the end windings... + + If(Flag_Cir) + GlobalTerm { NeverDt[ Dof{Uz} , {Iz} ] ; In Resistance_Cir ; } + GlobalTerm { NeverDt[ Resistance[] * Dof{Iz} , {Iz} ] ; In Resistance_Cir ; } + + GlobalTerm { [ Dof{Uz} , {Iz} ] ; In Inductance_Cir ; } + GlobalTerm { DtDof [ Inductance[] * Dof{Iz} , {Iz} ] ; In Inductance_Cir ; } + + GlobalTerm { NeverDt[ Dof{Iz} , {Iz} ] ; In Capacitance_Cir ; } + GlobalTerm { DtDof [ Capacitance[] * Dof{Uz} , {Iz} ] ; In Capacitance_Cir ; } + + GlobalTerm { [ 0. * Dof{Iz} , {Iz} ] ; In DomainZt_Cir ; } + GlobalTerm { [ 0. * Dof{Uz} , {Iz} ] ; In DomainZt_Cir ; } + + GlobalEquation { + Type Network ; NameOfConstraint ElectricalCircuit ; + { Node {I}; Loop {U}; Equation {I}; In DomainC ; } + { Node {Ib}; Loop {Ub}; Equation {Ub}; In DomainB ; } + { Node {Iz}; Loop {Uz}; Equation {Uz}; In DomainZt_Cir ; } + } + EndIf + } + } + + + //-------------------------------------------------------------------------- + // Mechanics + //-------------------------------------------------------------------------- + { Name Mechanical ; Type FemEquation ; + Quantity { + { Name V ; Type Global ; NameOfSpace Velocity [V] ; } // velocity + { Name P ; Type Global ; NameOfSpace Position [P] ; } // position + } + Equation { + GlobalTerm { DtDof [ Inertia * Dof{V} , {V} ] ; In DomainKin ; } + GlobalTerm { [ Friction[] * Dof{V} , {V} ] ; In DomainKin ; } + GlobalTerm { [ -Fmag[] , {V} ] ; In DomainKin ; } + + GlobalTerm { DtDof [ Dof{P} , {P} ] ; In DomainKin ; } + GlobalTerm { [-Dof{V} , {P} ] ; In DomainKin ; } + } + } + +} + +//----------------------------------------------------------------------------------------------- + +Resolution { + + { Name TimeDomain ; + System { + { Name A ; NameOfFormulation MagDyn_a_2D ; } + } + Operation { + CreateDir["res/"]; + If[ Clean_Results==1 ]{ + DeleteFile["res/temp.dat"]; + DeleteFile["res/Tr.dat"]; DeleteFile["res/Ts.dat"]; DeleteFile["res/Tmb.dat"]; + DeleteFile["res/Ua.dat"]; DeleteFile["res/Ub.dat"]; DeleteFile["res/Uc.dat"]; + DeleteFile["res/Ia.dat"]; DeleteFile["res/Ib.dat"]; DeleteFile["res/Ic.dat"]; + DeleteFile["res/Flux_a.dat"]; DeleteFile["res/Flux_b.dat"]; DeleteFile["res/Flux_c.dat"]; + DeleteFile["res/Flux_d.dat"]; DeleteFile["res/Flux_q.dat"]; DeleteFile["res/Flux_0.dat"]; + } + InitMovingBand2D[MB] ; + MeshMovingBand2D[MB] ; + InitSolution[A] ; + If[Flag_ParkTransformation && Flag_SrcType_Stator==1]{ PostOperation[ThetaPark_IABC] ; } + If[!Flag_NL]{ + Generate[A] ; Solve[A] ; + } + Else{ + //IterativeLoop[Nb_max_iter, stop_criterion, relaxation_factor] + // { GenerateJac[A] ; SolveJac[A] ; } + IterativeLoopN[ Nb_max_iter, relaxation_factor, + System { {A, reltol, abstol, Solution MeanL2Norm}} ] + { GenerateJac[A] ; SolveJac[A] ; } + } + SaveSolution[A] ; + PostOperation[Get_LocalFields] ; + PostOperation[Get_GlobalQuantities] ; + } + } + + { Name TimeDomain_Loop ; + System { + { Name A ; NameOfFormulation MagDyn_a_2D ; } + } + Operation { + CreateDir["res/"]; + If[ Clean_Results==1 ]{ + DeleteFile["res/temp.dat"]; + DeleteFile["res/Tr.dat"]; DeleteFile["res/Ts.dat"]; DeleteFile["res/Tmb.dat"]; + DeleteFile["res/Ua.dat"]; DeleteFile["res/Ub.dat"]; DeleteFile["res/Uc.dat"]; + DeleteFile["res/Ia.dat"]; DeleteFile["res/Ib.dat"]; DeleteFile["res/Ic.dat"]; + DeleteFile["res/Flux_a.dat"]; DeleteFile["res/Flux_b.dat"]; DeleteFile["res/Flux_c.dat"]; + DeleteFile["res/Flux_d.dat"]; DeleteFile["res/Flux_q.dat"]; DeleteFile["res/Flux_0.dat"]; + } + InitMovingBand2D[MB] ; + MeshMovingBand2D[MB] ; + InitSolution[A] ; + TimeLoopTheta[time0, timemax, delta_time, 1.]{ // Euler implicit (1) -- Crank-Nicolson (0.5) + If[Flag_ParkTransformation && Flag_SrcType_Stator==1]{ PostOperation[ThetaPark_IABC] ; } + If[!Flag_NL]{ + Generate[A]; Solve[A]; + } + Else{ + // IterativeLoop[Nb_max_iter, stop_criterion, relaxation_factor] { + // GenerateJac[A] ; SolveJac[A] ; } + IterativeLoopN[ + Nb_max_iter, relaxation_factor, System { {A, reltol, abstol, Solution MeanL2Norm}} ]{ + GenerateJac[A] ; SolveJac[A] ; } + } + SaveSolution[A]; + + PostOperation[Get_LocalFields] ; + If[ $TimeStep > 1 ]{ + PostOperation[Get_GlobalQuantities] ; + } + ChangeOfCoordinates[ NodesOf[Rotor_Moving], RotatePZ[delta_theta]] ; + MeshMovingBand2D[MB] ; + } + } + } + + { Name FrequencyDomain ; + System { + { Name A ; NameOfFormulation MagDyn_a_2D ; Type ComplexValue ; Frequency Freq ; } + } + Operation { + If[ Clean_Results==1 && wr == 0.]{ + DeleteFile["res/Tr.dat"]; DeleteFile["res/Ts.dat"]; DeleteFile["res/Tmb.dat"]; + DeleteFile["res/Ua.dat"]; DeleteFile["res/Ub.dat"]; DeleteFile["res/Uc.dat"]; + DeleteFile["res/Ia.dat"]; DeleteFile["res/Ib.dat"]; DeleteFile["res/Ic.dat"]; + } + SetTime[wr]; + InitMovingBand2D[MB] ; + MeshMovingBand2D[MB] ; + Generate[A] ; Solve[A] ; SaveSolution[A]; + PostOperation[Map_LocalFields] ; + PostOperation[Torque_Emf_Flux] ; + } + } + + /* + { Name MagDyn_Kin ; + System { + { Name A ; NameOfFormulation MagDyn_a_2D ; } + { Name M ; NameOfFormulation Mechanical ; } + } + Operation { + ChangeOfCoordinates [ NodesOf[Rotor_Moving], RotatePZ[theta0] ] ; // Initial position (supposing initial mesh with angleR=0) + InitMovingBand2D[MB] ; MeshMovingBand2D[MB] ; + + InitSolution[A] ; SaveSolution[A] ; + InitSolution[M] ; SaveSolution[M] ; + + TimeLoopTheta[time0, timemax, delta_time, 1.]{ + Generate[A] ; Solve[A] ; SaveSolution[A] ; + PostOperation[MagDyn_a_2D] ; + + Generate[M] ; Solve[M] ; SaveSolution[M] ; + PostOperation[Mechanical] ; + + ChangeOfCoordinates [ NodesOf[Rotor_Moving], RotatePZ[#77-#66] ] ; + Evaluate[ #77#66 ] ; //Keep track of previous angular position + MeshMovingBand2D[MB] ; + } + } + } + */ + +} + +//----------------------------------------------------------------------------------------------- + +PostProcessing { + + { Name MagSta_a_2D ; NameOfFormulation MagSta_a_2D ; + PostQuantity { + { Name a ; Value { Term { [ {a} ] ; In Domain ; Jacobian Vol ; } } } + { Name az ; Value { Term { [ CompZ[{a}] ] ; In Domain ; Jacobian Vol ; } } } + { Name b ; Value { Term { [ {d a} ] ; In Domain ; Jacobian Vol ; } } } + { Name boundary ; Value { Term { [ {d a} ] ; In Dummy ; Jacobian Vol ; } } } + { Name br ; Value { Term { [ br[] ] ; In DomainM ; Jacobian Vol ; } } } + + { Name Flux ; Value { Integral { [ SymmetryFactor*AxialLength*Idir[]*NbWires[]/SurfCoil[]* CompZ[{a}] ] ; + In Inds ; Jacobian Vol ; Integration I1 ; } } } + { Name Force_vw ; Value { + Integral { Type Global ; [ 0.5 * nu[] * VirtualWork [{d a}] * AxialLength ]; + In ElementsOf[Rotor_Airgap, OnOneSideOf Rotor_Bnd_MB]; + Jacobian Vol ; Integration I1 ; } } } + + { Name Torque_Maxwell ; Value { + Integral { + [ CompZ [ XYZ[] /\ (T_max[{d a}] * XYZ[]) ]*2*Pi*AxialLength/SurfaceArea[] ] ; + In Domain ; Jacobian Vol ; Integration I1; } } } + + { Name Torque_vw ; Value { + Integral { Type Global ; + [ CompZ[ 0.5 * nu[] * XYZ[] /\ VirtualWork[{d a}] ] * AxialLength ]; + In ElementsOf[Rotor_Airgap, OnOneSideOf Rotor_Bnd_MB]; + Jacobian Vol ; Integration I1 ; } } } + + { Name U ; Value { + Term { [ {Ub} ] ; In DomainB ; } + Term { [ {Uz} ] ; In DomainZt_Cir ; } + } } + + { Name I ; Value { + Term { [ {Ib} ] ; In DomainB ; } + Term { [ {Iz} ] ; In DomainZt_Cir ; } + } } + + } + } + + { Name MagDyn_a_2D ; NameOfFormulation MagDyn_a_2D ; + PostQuantity { + { Name a ; Value { Term { [ {a} ] ; In Domain ; Jacobian Vol ; } } } + { Name az ; Value { Term { [ CompZ[{a}] ] ; In Domain ; Jacobian Vol ; } } } + + { Name b ; Value { Term { [ {d a} ] ; In Domain ; Jacobian Vol ; } } } + { Name boundary ; Value { Term { [ 1 ] ; In Dummy ; Jacobian Vol ; } } } // Dummy quantity + { Name b_radial ; Value { Term { [ {d a}* Vector[ Cos[AngularPosition[]#4], Sin[#4], 0.] ] ; In Domain ; Jacobian Vol ; } } } + { Name b_tangent ; Value { Term { [ {d a}* Vector[ -Sin[AngularPosition[]#4], Cos[#4], 0.] ] ; In Domain ; Jacobian Vol ; } } } + + { Name js ; Value { Term { [ js[] ] ; In DomainS ; Jacobian Vol ; } } } + { Name br ; Value { Term { [ br[] ] ; In DomainM ; Jacobian Vol ; } } } + + { Name j ; Value { + Term { [ -sigma[]*(Dt[{a}]+{ur}) ] ; In DomainC ; Jacobian Vol ; } + Term { [ sigma[]*(Velocity[] *^ {d a}) ] ; In DomainV ; Jacobian Vol ; } + } + } + { Name ir ; Value { Term { [ {ir} ] ; In Inds ; Jacobian Vol ; } } } + + { Name jz ; Value { + Term { [ CompZ[-sigma[]*(Dt[{a}]+{ur})] ] ; In DomainC ; Jacobian Vol ; } + Term { [ CompZ[ sigma[]*(Velocity[]*^{d a}) ] ] ; In DomainV ; Jacobian Vol ; } + } + } + + { Name rhoj2 ; + Value { + Term { [ sigma[]*SquNorm[ Dt[{a}]+{ur}] ] ; In Region[{DomainC,-DomainV}] ; Jacobian Vol ; } + Term { [ sigma[]*SquNorm[ Dt[{a}]+{ur}-Velocity[]*^{d a} ] ] ; In DomainV ; Jacobian Vol ; } + Term { [ 1./sigma[]*SquNorm[ IA[]*{ir} ] ] ; In PhaseA ; Jacobian Vol ; } + Term { [ 1./sigma[]*SquNorm[ IB[]*{ir} ] ] ; In PhaseB ; Jacobian Vol ; } + Term { [ 1./sigma[]*SquNorm[ IC[]*{ir} ] ] ; In PhaseC ; Jacobian Vol ; } + } + } + + { Name JouleLosses ; + Value { + Integral { [ sigma[] * SquNorm[ Dt[{a}]+{ur}-Velocity[]*^{d a} ] ] ; In Region[{DomainC,-DomainV}] ; Jacobian Vol ; Integration I1 ; } + Integral { [ sigma[] * SquNorm[ Dt[{a}]+{ur}-Velocity[]*^{d a} ] ] ; In DomainV ; Jacobian Vol ; Integration I1 ; } + Integral { [ 1./sigma[]*SquNorm[ IA[]*{ir} ] ] ; In PhaseA ; Jacobian Vol ; Integration I1 ; } + Integral { [ 1./sigma[]*SquNorm[ IB[]*{ir} ] ] ; In PhaseB ; Jacobian Vol ; Integration I1 ; } + Integral { [ 1./sigma[]*SquNorm[ IC[]*{ir} ] ] ; In PhaseC ; Jacobian Vol ; Integration I1 ; } + } + } + + { Name Flux ; Value { Integral { [ SymmetryFactor*AxialLength*Idir[]*NbWires[]/SurfCoil[]* CompZ[{a}] ] ; + In Inds ; Jacobian Vol ; Integration I1 ; } } } + + { Name Force_vw ; // Force computation by Virtual Works + Value { + Integral { + Type Global ; [ 0.5 * nu[] * VirtualWork [{d a}] * AxialLength ]; + In ElementsOf[Rotor_Airgap, OnOneSideOf Rotor_Bnd_MB]; Jacobian Vol ; Integration I1 ; } + } + } + + { Name Torque_vw ; Value { // Torque computation via Virtual Works + Integral { Type Global ; + [ CompZ[ 0.5 * nu[] * XYZ[] /\ VirtualWork[{d a}] ] * AxialLength ]; + In ElementsOf[Rotor_Airgap, OnOneSideOf Rotor_Bnd_MB]; Jacobian Vol ; Integration I1 ; } + } + } + + + { Name Torque_Maxwell ; // Torque computation via Maxwell stress tensor + Value { + Integral { + [ CompZ [ XYZ[] /\ (T_max[{d a}] * XYZ[]) ] * 2*Pi*AxialLength/SurfaceArea[] ] ; + In Domain ; Jacobian Vol ; Integration I1; } + } + } + + { Name Torque_Maxwell_cplx ; // Torque computation via Maxwell stress tensor + Value { + Integral { + [ CompZ [ XYZ[] /\ (T_max_cplx[{d a}] * XYZ[]) ] * 2*Pi*AxialLength/SurfaceArea[] ] ; + In Domain ; Jacobian Vol ; Integration I1; } + } + } + + { Name ComplexPower ; // S = P + i*Q + Value { + Integral { [ Complex[ sigma[]*SquNorm[Dt[{a}]+{ur}], nu[]*SquNorm[{d a}] ] ] ; + In Region[{DomainC,-DomainV}] ; Jacobian Vol ; Integration I1 ; } + Integral { [ Complex[ sigma[]*SquNorm[Dt[{a}]+{ur}-Velocity[]*^{d a}], nu[]*SquNorm[{d a}] ] ] ; + In DomainV ; Jacobian Vol ; Integration I1 ; } + } + } + + { Name U ; Value { + Term { [ {U} ] ; In DomainC ; } + Term { [ {Ub} ] ; In DomainB ; } + Term { [ {Uz} ] ; In DomainZt_Cir ; } + } } + + { Name I ; Value { + Term { [ {I} ] ; In DomainC ; } + Term { [ {Ib} ] ; In DomainB ; } + Term { [ {Iz} ] ; In DomainZt_Cir ; } + } } + + { Name S ; Value { + Term { [ {U}*Conj[{I}] ] ; In DomainC ; } + Term { [ {Ub}*Conj[{Ib}] ] ; In DomainB ; } + Term { [ {Uz}*Conj[{Iz}] ] ; In DomainZt_Cir ; } + } } + + { Name Velocity ; Value { + Term { [ Velocity[] ] ; In Domain ; Jacobian Vol ; } + } + } + + // For getting the value of some functions: + { Name RotorPosition_deg ; Value { Term { Type Global; [ RotorPosition_deg[] ] ; In DomainDummy ; } } } + { Name Theta_Park_deg ; Value { Term { Type Global; [ Theta_Park_deg[] ] ; In DomainDummy ; } } } + { Name IA ; Value { Term { Type Global; [ IA[] ] ; In DomainDummy ; } } } + { Name IB ; Value { Term { Type Global; [ IB[] ] ; In DomainDummy ; } } } + { Name IC ; Value { Term { Type Global; [ IC[] ] ; In DomainDummy ; } } } + + { Name Flux_d ; Value { Term { Type Global; [ CompX[Flux_dq0[]] ] ; In DomainDummy ; } } } + { Name Flux_q ; Value { Term { Type Global; [ CompY[Flux_dq0[]] ] ; In DomainDummy ; } } } + { Name Flux_0 ; Value { Term { Type Global; [ CompZ[Flux_dq0[]] ] ; In DomainDummy ; } } } + } + } + + { Name Mechanical ; NameOfFormulation Mechanical ; + PostQuantity { + { Name P ; Value { Term { [ {P} ] ; In DomainKin ; } } } //Position + { Name V ; Value { Term { [ {V} ] ; In DomainKin ; } } } //Velocity + { Name Vrpm ; Value { Term { [ {V}*30/Pi ] ; In DomainKin ; } } } //Velocity in rpm + } + } + +} + +//----------------------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------------------- + +If (Flag_ParkTransformation) +PostOperation ThetaPark_IABC UsingPost MagDyn_a_2D { + Print[ RotorPosition_deg, OnRegion DomainDummy, Format Table, LastTimeStepOnly, File StrCat[Dir, StrCat["temp",ExtGnuplot]], + SendToServer "Output/1RotorPosition", Color "LightYellow" ]; + Print[ Theta_Park_deg, OnRegion DomainDummy, Format Table, LastTimeStepOnly, File StrCat[Dir, StrCat["temp",ExtGnuplot]], + SendToServer "Output/1Theta_Park", Color "LightYellow" ]; + Print[ IA, OnRegion DomainDummy, Format Table, LastTimeStepOnly, File StrCat[Dir, StrCat["temp",ExtGnuplot]], SendToServer "Output/2IA", Color "Pink" ]; + Print[ IB, OnRegion DomainDummy, Format Table, LastTimeStepOnly, File StrCat[Dir, StrCat["temp",ExtGnuplot]], SendToServer "Output/2IB", Color "Yellow" ]; + Print[ IC, OnRegion DomainDummy, Format Table, LastTimeStepOnly, File StrCat[Dir, StrCat["temp",ExtGnuplot]], SendToServer "Output/2IC", Color "LightGreen" ]; +} +EndIf +PostOperation Get_LocalFields UsingPost MagDyn_a_2D { + Print[ ir, OnElementsOf Stator_Inds, File StrCat[Dir, StrCat["ir_stator",ExtGmsh]], LastTimeStepOnly, AppendTimeStepToFileName Flag_SaveAllSteps] ; + Print[ ir, OnElementsOf Rotor_Inds, File StrCat[Dir, StrCat["ir_rotor",ExtGmsh]], LastTimeStepOnly, AppendTimeStepToFileName Flag_SaveAllSteps] ; + //Print[ br, OnElementsOf #{DomainM}, File StrCat[Dir, StrCat["b",ExtGmsh]], LastTimeStepOnly, AppendTimeStepToFileName Flag_SaveAllSteps] ; + Print[ b, OnElementsOf Domain, File StrCat[Dir, StrCat["b",ExtGmsh]], LastTimeStepOnly, AppendTimeStepToFileName Flag_SaveAllSteps] ; + Print[ boundary, OnElementsOf Dummy, File StrCat[Dir, StrCat["bnd",ExtGmsh]], LastTimeStepOnly, AppendTimeStepToFileName Flag_SaveAllSteps] ; + Print[ az, OnElementsOf Domain, File StrCat[Dir, StrCat["a",ExtGmsh]], LastTimeStepOnly, AppendTimeStepToFileName Flag_SaveAllSteps ] ; +} + +PostOperation Get_GlobalQuantities UsingPost MagDyn_a_2D { + If(!Flag_Cir) + If(!Flag_ParkTransformation) + Print[ I, OnRegion PhaseA_pos, Format Table, + File > StrCat[Dir, StrCat["Ia",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2IA", Color "Pink" ]; + Print[ I, OnRegion PhaseB_pos, Format Table, + File > StrCat[Dir, StrCat["Ib",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2IB", Color "Yellow" ]; + Print[ I, OnRegion PhaseC_pos, Format Table, + File > StrCat[Dir, StrCat["Ic",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2IC", Color "LightGreen" ]; + EndIf + + Print[ U, OnRegion PhaseA_pos, Format Table, + File > StrCat[Dir, StrCat["Ua",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/30UA", Color "Pink" ]; + Print[ U, OnRegion PhaseB_pos, Format Table, + File > StrCat[Dir, StrCat["Ub",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/31UB", Color "Yellow" ]; + Print[ U, OnRegion PhaseC_pos, Format Table, + File > StrCat[Dir, StrCat["Uc",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/32UC", Color "LightGreen" ]; + EndIf + If(Flag_Cir && Flag_SrcType_Stator==2) + Print[ I, OnRegion Input1, Format Table, + File > StrCat[Dir, StrCat["Ia",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2IA", Color "Pink" ]; + Print[ I, OnRegion Input2, Format Table, + File > StrCat[Dir, StrCat["Ib",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2IB", Color "Yellow" ]; + Print[ I, OnRegion Input3, Format Table, + File > StrCat[Dir, StrCat["Ic",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2IC", Color "LightGreen" ]; + Print[ U, OnRegion Input1, Format Table, + File > StrCat[Dir, StrCat["Ua",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/30UA", Color "Pink" ]; + Print[ U, OnRegion Input2, Format Table, + File > StrCat[Dir, StrCat["Ub",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/31UB", Color "Yellow" ]; + Print[ U, OnRegion Input3, Format Table, + File > StrCat[Dir, StrCat["Uc",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/32UC", Color "LightGreen" ]; + EndIf + If(Flag_Cir && Flag_SrcType_Stator==0) + Print[ I, OnRegion R1, Format Table, + File > StrCat[Dir, StrCat["Ia",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2IA", Color "Pink" ]; + Print[ I, OnRegion R2, Format Table, + File > StrCat[Dir, StrCat["Ib",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2IB", Color "Yellow" ]; + Print[ I, OnRegion R3, Format Table, + File > StrCat[Dir, StrCat["Ic",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2IC", Color "LightGreen" ]; + Print[ U, OnRegion R1, Format Table, + File > StrCat[Dir, StrCat["Ua",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/30UA", Color "Pink" ]; + Print[ U, OnRegion R2, Format Table, + File > StrCat[Dir, StrCat["Ub",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/31UB", Color "Yellow" ]; + Print[ U, OnRegion R3, Format Table, + File > StrCat[Dir, StrCat["Uc",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/32UC", Color "LightGreen" ]; + EndIf + + + Print[ I, OnRegion RotorC, Format Table, + File > StrCat[Dir, StrCat["Irotor",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/2Ir", Color "LightYellow" ]; + + Print[ Torque_Maxwell[Rotor_Airgap], OnGlobal, Format TimeTable, + File > StrCat[Dir, StrCat["Tr",ExtGnuplot]], LastTimeStepOnly, Store 54, SendToServer my_output, Color "LightYellow" ]; + Print[ Torque_Maxwell[Stator_Airgap], OnGlobal, Format TimeTable, + File > StrCat[Dir, StrCat["Ts",ExtGnuplot]], LastTimeStepOnly, Store 55, SendToServer "Output/41T_stator", Color "LightYellow" ]; + Print[ Torque_Maxwell[MB], OnGlobal, Format TimeTable, + File > StrCat[Dir, StrCat["Tmb",ExtGnuplot]], LastTimeStepOnly, Store 56, SendToServer "Output/42T_mb", Color "LightYellow" ]; + //Print[ Torque_vw, OnRegion NodesOf[Rotor_Bnd_MB], Format RegionValue, + // File > StrCat[Dir, StrCat["Tr_vw",ExtGnuplot]], LastTimeStepOnly, Store 54, SendToServer "Output/1T_rotor_vw" ]; + + If(Flag_SrcType_Stator) + Print[ Flux[PhaseA], OnGlobal, Format TimeTable, + File > StrCat[Dir, StrCat["Flux_a",ExtGnuplot]], LastTimeStepOnly, Store 11, SendToServer "Output/50Flux_a", Color "Pink" ]; + Print[ Flux[PhaseB], OnGlobal, Format TimeTable, + File > StrCat[Dir, StrCat["Flux_b",ExtGnuplot]], LastTimeStepOnly, Store 22, SendToServer "Output/51Flux_b", Color "Yellow" ]; + Print[ Flux[PhaseC], OnGlobal, Format TimeTable, + File > StrCat[Dir, StrCat["Flux_c",ExtGnuplot]], LastTimeStepOnly, Store 33, SendToServer "Output/52Flux_c", Color "LightGreen"]; + + If(Flag_ParkTransformation && Flag_SrcType_Stator) + Print[ Flux_d, OnRegion DomainDummy, Format TimeTable, + File > StrCat[Dir, StrCat["Flux_d",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/60Flux_d", Color "LightYellow" ]; + Print[ Flux_q, OnRegion DomainDummy, Format TimeTable, + File > StrCat[Dir, StrCat["Flux_q",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/61Flux_q", Color "LightYellow" ]; + Print[ Flux_0, OnRegion DomainDummy, Format TimeTable, + File > StrCat[Dir, StrCat["Flux_0",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/62Flux_0", Color "LightYellow" ]; + EndIf + EndIf +} + + +PostOperation Joule_Losses UsingPost MagDyn_a_2D { + Print[ JouleLosses[Rotor], OnGlobal, Format TimeTable, + File > StrCat[Dir, StrCat["P",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/3P_rotor" ]; + Print[ JouleLosses[Rotor_Fe], OnGlobal, Format TimeTable, + File > StrCat[Dir, StrCat["P_Fe",ExtGnuplot]], LastTimeStepOnly, SendToServer "Output/3P_rotor_fe" ]; +} + +/* +PostOperation Mechanical UsingPost Mechanical { + Print[ P, OnRegion DomainKin, File > StrCat[Dir, StrCat["P", ExtGnuplot]], + Format Table, Store 77, LastTimeStepOnly, SendToServer "Output/3Position"] ; + Print[ V, OnRegion DomainKin, File > StrCat[Dir, StrCat["V", ExtGnuplot]], + Format Table, LastTimeStepOnly, SendToServer "Output/4Velocity"] ; +} +*/ diff --git a/contrib/mobile/Android/res/raw/magnet_data_pro b/contrib/mobile/Android/res/raw/magnet_data_pro new file mode 100644 index 0000000000..3e0a76ce52 --- /dev/null +++ b/contrib/mobile/Android/res/raw/magnet_data_pro @@ -0,0 +1,16 @@ + +DefineConstant[ Val_Rint = {0.15, Min 0.2, Max 1, Step 0.1, + Path "Parameters/Geometry/1", + Label "Internal shell radius (m)"} ]; + +DefineConstant[ Val_Rext = {0.25, Min Val_Rint, Max 0.5, Step 0.1, + Path "Parameters/Geometry/2", + Label "External shell radius (m)"}]; + +AIR = 100; +AIR_INF = 101; +AIR_GAP = 102; +MAGNET = 103; +CORE = 104; +LINE_INF = 105; +LINE_X = 106; diff --git a/contrib/mobile/Android/res/raw/magnet_geo b/contrib/mobile/Android/res/raw/magnet_geo new file mode 100644 index 0000000000..c0c7815711 --- /dev/null +++ b/contrib/mobile/Android/res/raw/magnet_geo @@ -0,0 +1,93 @@ +Include "magnet_data.pro"; + +DefineConstant[ h = {0.14, Min 0.1, Max 0.2, Step 0.01, + Path "Parameters/Geometry", + Label "Core height (m)"} ] ; + +DefineConstant[ l = {0.14, Min 0.05, Max 0.2, Step 0.01, + Path "Parameters/Geometry", + Label "Core width (m)"} ] ; + +DefineConstant[ d = {0.03, Min 0.01, Max 0.05, Step 0.002, + Path "Parameters/Geometry", + Label "Core tickness (m)"} ] ; + +DefineConstant[ e = {5e-3, Min 5e-4, Max d, Step 1e-3, + Path "Parameters/Geometry", + Label "Air gap (m)", Highlight "LightYellow"} ] ; + +DefineConstant[ ha = {0.03, Min 0.01, Max 0.1, Step 0.01, + Path "Parameters/Geometry", + Label "Magnet height (m)"} ] ; + +lc0 = d / 5 ; +lc1 = e / 2 ; +lc2 = (Val_Rext - Val_Rint) / 8. ; + +Point(1) = {0, 0, 0, lc0}; +Point(2) = {-l/2, 0, 0, lc0}; +Point(3) = {-l/2, h/2, 0, lc0}; +Point(4) = {l/2, 0, 0, lc1}; +Point(5) = {l/2, h/2, 0, lc0}; +Point(6) = {-l/2, ha/2, 0, lc0}; +Point(7) = {-l/2+d, ha/2, 0, lc0}; +Point(8) = {-l/2+d, 0, 0, lc0}; +Point(9) = {l/2-d, 0, 0, lc1}; +Point(10) = {l/2-d, h/2-d, 0, lc0}; +Point(11) = {-l/2+d, h/2-d, 0, lc0}; +Point(12) = {l/2, e/2, 0, lc1}; +Point(13) = {l/2-d, e/2, 0, lc1}; + +Point(30) = {Val_Rint, 0, 0, lc2}; +Point(31) = {Val_Rext, 0, 0, lc2}; +Point(32) = {0, Val_Rint, 0, lc2}; +Point(33) = {0, Val_Rext, 0, lc2}; +Point(34) = {-Val_Rext, 0, 0, lc2}; +Point(35) = {-Val_Rint, 0, 0, lc2}; + +Line(1) = {34, 35}; +Line(2) = {35, 2}; +Line(3) = {2, 8}; +Line(4) = {8, 1}; +Line(5) = {1, 9}; +Line(6) = {9, 4}; +Line(7) = {4, 30}; +Line(8) = {30, 31}; +Line(9) = {2, 6}; +Line(10) = {6, 3}; +Line(11) = {3, 5}; +Line(12) = {5, 12}; +Line(13) = {12, 4}; +Line(14) = {9, 13}; +Line(15) = {13, 10}; +Line(16) = {10, 11}; +Line(17) = {11, 7}; +Line(18) = {7, 8}; +Line(19) = {7, 6}; +Line(20) = {13, 12}; +Circle(21) = {35, 1, 32}; +Circle(22) = {32, 1, 30}; +Circle(23) = {34, 1, 33}; +Circle(24) = {33, 1, 31}; + +Line Loop(25) = {21, 22, 8, -24, -23, 1}; +Plane Surface(26) = {25}; +Line Loop(27) = - {22, -7, -13, -12, -11, -10, -9, -2, 21}; +Plane Surface(28) = {27}; +Line Loop(29) = - {11, 12, -20, 15, 16, 17, 19, 10}; +Plane Surface(30) = {29}; +Line Loop(31) = {19, -9, 3, -18}; +Plane Surface(32) = {31}; +Line Loop(33) = - {20, 13, -6, 14}; +Plane Surface(34) = {33}; +Line Loop(35) = {15, 16, 17, 18, 4, 5, 14}; +Plane Surface(36) = {35}; + +// physical entities (for which elements will be saved) +Physical Surface(AIR) = {28, 36}; +Physical Surface(AIR_INF) = {26}; +Physical Surface(AIR_GAP) = {34}; +Physical Surface(MAGNET) = {32}; +Physical Surface(CORE) = {30}; +Physical Line(LINE_INF) = {23, 24}; +Physical Line(LINE_X) = {1:8}; diff --git a/contrib/mobile/Android/res/raw/magnet_pro b/contrib/mobile/Android/res/raw/magnet_pro new file mode 100644 index 0000000000..a18c7cdf4f --- /dev/null +++ b/contrib/mobile/Android/res/raw/magnet_pro @@ -0,0 +1,69 @@ +/* + To solve the problem + with scalar potential, type 'getdp test -solve MagSta_phi -pos phi' + with vector potential, type 'getdp test -solve MagSta_a -pos a' +*/ + +Include "magnet_data.pro"; + +Group { + // AIR, AIR_INF, etc. are variables defined in core.txt, and correspond to the + // tags of physical regions in the mesh + Air = Region[ AIR ]; + AirInf = Region[ AIR_INF ]; + Core = Region[ CORE ]; + AirGap = Region[ AIR_GAP ]; + Magnet = Region[ MAGNET ]; + + // These are the generic group names that are used in "Magnetostatics.pro" + Domain_S = Region[ {} ] ; + Domain_Inf = Region[ AirInf ] ; + Domain_M = Region[ Magnet ] ; + Domain_Mag = Region[ {Air, Core, AirGap} ] ; + Dirichlet_a_0 = Region[ LINE_INF ] ; + Dirichlet_phi_0 = Region[ {LINE_X, LINE_INF} ] ; +} + +Function { + mu0 = 4.e-7 * Pi ; + + // DefineConstant is used to define a default value for murCore; this value + // can be changed interactively by the ONELAB server + DefineConstant[ murCore = {200., Min 1, Max 1000, Step 10, + Label "Core relative permeability", + Path "Parameters/Materials"} ]; + + nu [ Region[{Air, AirInf, AirGap, Magnet}] ] = 1. / mu0 ; + nu [ Core ] = 1. / (murCore * mu0) ; + + mu [ Region[{Air, AirInf, AirGap, Magnet}] ] = mu0 ; + mu [ Core ] = murCore * mu0; + + DefineConstant[ Hc = {920000, Label "Magnet coercive field (A/m)", + Path "Parameters/Materials"} ]; + hc [ Magnet ] = Vector[0., Hc, 0.] ; +} + +Include "magnetostatics.pro" + +eps = 1.e-5 ; + +Printf[ "murCore: %f",murCore ] ; + +PostOperation { + { Name phi ; NameOfPostProcessing MagSta_phi; + Operation { + Print[ phi, OnElementsOf Domain, File "phi.pos" ] ; + Print[ b, OnElementsOf Domain, File "b_phi.pos" ] ; + Print[ b, OnLine {{-0.07,eps,0}{0.09,eps,0}} {500}, File "b_phi.txt", Format Table ] ; + } + } + { Name a ; NameOfPostProcessing MagSta_a; + Operation { + Print[ a, OnElementsOf Domain, File "a.pos"] ; + Print[ b, OnElementsOf Domain, File "b_a.pos" ] ; + Print[ h, OnElementsOf Domain, File "h_a.pos" ] ; + Print[ b, OnLine {{-0.07,eps,0}{0.09,eps,0}} {500}, File "b_a.txt" , Format Table ] ; + } + } +} diff --git a/contrib/mobile/Android/res/raw/magnetostatics_pro b/contrib/mobile/Android/res/raw/magnetostatics_pro new file mode 100644 index 0000000000..4c9c07d5c5 --- /dev/null +++ b/contrib/mobile/Android/res/raw/magnetostatics_pro @@ -0,0 +1,209 @@ +Group { + // Input groups: + DefineGroup[ Domain_M = {{}, Label "Permanent magnets", + Path "Regions/0Sources"}, + Domain_S = {{}, Label "Inductor (imposed j_s)", + Path "Regions/0Sources"}, + Domain_Inf = {{}, Label "Infinite domain (spherical shell)", + Path "Regions/0Special regions", Closed "1"}, + Domain_Mag = {{}, Label "Passive magnetic regions", + Path "Regions/Other regions"}, + Dirichlet_phi_0 = {{}, Label "h_t = 0", Closed "1", + Path "Regions/0Boundary conditions"}, + Dirichlet_a_0 = {{}, Label "b_n = 0", + Path "Regions/0Boundary conditions"} ]; + + DefineGroup[ Domain = {{Domain_Mag, Domain_M, Domain_S, Domain_Inf}, + Label "Computational domain", Path "Regions", Visible 0} ]; +} + +Function{ + // Input constants: + DefineConstant[ Val_Rint, Val_Rext // interior/exterior radius of Domain_Inf + ]; + + // Input functions: + DefineFunction[ mu, // magnetic permeability + nu, // magnetic reluctivity + hc, // coercive magnetic field + js // source current density + ]; + + // remove this: only for demo + //DefineConstant[ hcx = {0, Label "Coercive field h_x", Path "Sources"}]; + //DefineConstant[ hcy = {1000, Label "Coercive field h_y", Path "Sources"}]; + //hc[] = Vector[hcx,hcy,0]; + //mu[] = 4*Pi*10^-7; + //nu[] = 1/mu[]; +} + +Jacobian { + { Name JVol ; + Case { + { Region Domain_Inf ; Jacobian VolSphShell{Val_Rint, Val_Rext} ; } + { Region All ; Jacobian Vol ; } + } + } +} + +Integration { + { Name I1 ; + Case { + { Type Gauss ; + Case { + { GeoElement Triangle ; NumberOfPoints 4 ; } + { GeoElement Quadrangle ; NumberOfPoints 4 ; } + } + } + } + } +} + + +/* -------------------------------------------------------------------------- + MagSta_phi : Magnetic scalar potential phi formulation + -------------------------------------------------------------------------- */ + +Constraint { + { Name phi ; + Case { + { Region Dirichlet_phi_0 ; Value 0. ; } + } + } +} + +FunctionSpace { + { Name Hgrad_phi ; Type Form0 ; + BasisFunction { + { Name sn ; NameOfCoef phin ; Function BF_Node ; + Support Domain ; Entity NodesOf[ All ] ; } + } + Constraint { + { NameOfCoef phin ; EntityType NodesOf ; NameOfConstraint phi ; } + } + } +} + +Formulation { + { Name MagSta_phi ; Type FemEquation ; + Quantity { + { Name phi ; Type Local ; NameOfSpace Hgrad_phi ; } + } + Equation { + Galerkin { [ - mu[] * Dof{d phi} , {d phi} ] ; + In Domain ; Jacobian JVol ; Integration I1 ; } + + Galerkin { [ - mu[] * hc[] , {d phi} ] ; + In Domain_M ; Jacobian JVol ; Integration I1 ; } + } + } +} + +Resolution { + { Name MagSta_phi ; + System { + { Name A ; NameOfFormulation MagSta_phi ; } + } + Operation { + Generate[A] ; Solve[A] ; SaveSolution[A] ; + } + } +} + +PostProcessing { + { Name MagSta_phi ; NameOfFormulation MagSta_phi ; + Quantity { + { Name b ; Value { Local { [ - mu[] * {d phi} ] ; In Domain ; Jacobian JVol ; } + Local { [ - mu[] * hc[] ] ; In Domain_M ; Jacobian JVol ; } } } + { Name h ; Value { Local { [ - {d phi} ] ; In Domain ; Jacobian JVol ; } } } + { Name phi ; Value { Local { [ {phi} ] ; In Domain ; Jacobian JVol ; } } } + } + } +} + +PostOperation { + { Name MagSta_phi ; NameOfPostProcessing MagSta_phi; + Operation { + Print[ b, OnElementsOf Domain, File "MagSta_phi_b.pos" ] ; + Print[ h, OnElementsOf Domain, File "MagSta_phi_h.pos" ] ; + Print[ phi, OnElementsOf Domain, File "MagSta_phi_phi.pos" ] ; + } + } +} + +/* -------------------------------------------------------------------------- + MagSta_a : Magnetic vector potential a formulation (2D) + -------------------------------------------------------------------------- */ + +Constraint { + { Name a ; + Case { + { Region Dirichlet_a_0 ; Value 0. ; } + } + } +} + +FunctionSpace { + + { Name Hcurl_a ; Type Form1P ; + BasisFunction { + { Name se ; NameOfCoef ae ; Function BF_PerpendicularEdge ; + Support Domain ; Entity NodesOf[ All ] ; } + } + Constraint { + { NameOfCoef ae ; EntityType NodesOf ; NameOfConstraint a ; } + } + } + +} + +Formulation { + { Name MagSta_a ; Type FemEquation ; + Quantity { + { Name a ; Type Local ; NameOfSpace Hcurl_a ; } + } + Equation { + Galerkin { [ nu[] * Dof{d a} , {d a} ] ; + In Domain ; Jacobian JVol ; Integration I1 ; } + + Galerkin { [ hc[] , {d a} ] ; + In Domain_M ; Jacobian JVol ; Integration I1 ; } + + Galerkin { [ -js[] , {a} ] ; + In Domain_S ; Jacobian JVol ; Integration I1 ; } + } + } +} + +Resolution { + { Name MagSta_a ; + System { + { Name A ; NameOfFormulation MagSta_a ; } + } + Operation { + Generate[A] ; Solve[A] ; SaveSolution[A]; + } + } +} + +PostProcessing { + { Name MagSta_a ; NameOfFormulation MagSta_a ; + Quantity { + { Name a ; Value { Local { [ CompZ[{a}] ] ; In Domain ; Jacobian JVol ; } } } + { Name b ; Value { Local { [ {d a} ] ; In Domain ; Jacobian JVol ; } } } + { Name a ; Value { Local { [ {a} ] ; In Domain ; Jacobian JVol ; } } } + { Name h ; Value { Local { [ nu[] * {d a} ] ; In Domain ; Jacobian JVol ; } + Local { [ hc[] ] ; In Domain_M ; Jacobian JVol ; } } } + } + } +} + +PostOperation { + { Name MagSta_a ; NameOfPostProcessing MagSta_a; + Operation { + Print[ b, OnElementsOf Domain, File "MagSta_a_b.pos" ] ; + Print[ h, OnElementsOf Domain, File "MagSta_a_h.pos" ] ; + Print[ a, OnElementsOf Domain, File "MagSta_a_a.pos" ] ; + } + } +} diff --git a/contrib/mobile/Android/res/raw/pmsm_8p_circuit_pro b/contrib/mobile/Android/res/raw/pmsm_8p_circuit_pro new file mode 100644 index 0000000000..37e1ac3756 --- /dev/null +++ b/contrib/mobile/Android/res/raw/pmsm_8p_circuit_pro @@ -0,0 +1,123 @@ +// +// Circuit for Permanent Magnet Synchronous Generator - cbmag +// + +Group{ + // Dummy numbers for circuit definition + R1 = #55551 ; + R2 = #55552 ; + R3 = #55553 ; + + Input1 = #10001 ; + Input2 = #10002 ; + Input3 = #10003 ; + Input4 = #10004 ; + + Resistance_Cir = Region[{R1, R2, R3}]; + DomainZ_Cir = Region[ {Resistance_Cir} ]; + + DomainSource_Cir = Region[ {} ] ; + If(Flag_SrcType_Stator>1) + DomainSource_Cir += Region[ {Input1, Input2, Input3} ] ; + EndIf + + DomainZt_Cir = Region[ {DomainZ_Cir, DomainSource_Cir} ]; +} + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +Function { + // Open circuit - load - short circuit + DefineConstant[ ZR = {200, + Choices{1e-8, 200, 1e8}, Label "Load resistance", Path "Input/", Highlight "AliceBlue"} ]; + Resistance[#{R1, R2, R3}] = ZR ; +} + +// -------------------------------------------------------------------------- + +Constraint { + + If (SymmetryFactor<8) + If(Flag_SrcType_Stator==0) + { Name ElectricalCircuit ; Type Network ; + Case Circuit1 { + { Region Stator_Ind_Ap ; Branch {100,102} ; } + { Region Stator_Ind_Am ; Branch {103,102} ; } + { Region R1 ; Branch {103,100} ; } + } + Case Circuit2 { + { Region Stator_Ind_Bp ; Branch {200,202} ; } + { Region Stator_Ind_Bm ; Branch {203,202} ; } + { Region R2 ; Branch {203,200} ; } + } + Case Circuit3 { + { Region Stator_Ind_Cp ; Branch {300,302} ; } + { Region Stator_Ind_Cm ; Branch {303,302} ; } + { Region R3 ; Branch {303,300} ; } + } + } + EndIf + If (Flag_SrcType_Stator==2) + { Name ElectricalCircuit ; Type Network ; + Case Circuit1 { + { Region Input1 ; Branch {100,101} ; } + { Region Stator_Ind_Ap ; Branch {101,102} ; } + { Region Stator_Ind_Am ; Branch {103,102} ; } + { Region R1 ; Branch {103,100} ; } + } + Case Circuit2 { + { Region Input2 ; Branch {200,201} ; } + { Region Stator_Ind_Bp ; Branch {201,202} ; } + { Region Stator_Ind_Bm ; Branch {203,202} ; } + { Region R2 ; Branch {203,200} ; } + } + Case Circuit3 { + { Region Input3 ; Branch {300,301} ; } + { Region Stator_Ind_Cp ; Branch {301,302} ; } + { Region Stator_Ind_Cm ; Branch {303,302} ; } + { Region R3 ; Branch {303,300} ; } + } + } + EndIf + EndIf + + If(SymmetryFactor==8) + If(Flag_SrcType_Stator==0) // Only one physical region in geo allow per branch + { Name ElectricalCircuit ; Type Network ; + Case Circuit1 { + { Region PhaseA ; Branch {100,102} ; } + { Region R1 ; Branch {102,100} ; } + } + Case Circuit2 { + { Region PhaseB ; Branch {200,202} ; } + { Region R2 ; Branch {202,200} ; } + } + Case Circuit3 { + { Region PhaseC ; Branch {300,302} ; } + { Region R3 ; Branch {302,300} ; } + } + } + EndIf + If(Flag_SrcType_Stator==2) // Only one physical region in geo allow per branch + { Name ElectricalCircuit ; Type Network ; + Case Circuit1 { + { Region Input1 ; Branch {100,101} ; } + { Region PhaseA ; Branch {101,102} ; } + { Region R1 ; Branch {102,100} ; } + } + Case Circuit2 { + { Region Input2 ; Branch {200,201} ; } + { Region PhaseB ; Branch {201,202} ; } + { Region R2 ; Branch {202,200} ; } + } + Case Circuit3 { + { Region Input3 ; Branch {300,301} ; } + { Region PhaseC ; Branch {302,301} ; } + { Region R3 ; Branch {302,300} ; } + } + } + EndIf + EndIf +} + diff --git a/contrib/mobile/Android/res/raw/pmsm_data_geo b/contrib/mobile/Android/res/raw/pmsm_data_geo new file mode 100644 index 0000000000..c2760986cf --- /dev/null +++ b/contrib/mobile/Android/res/raw/pmsm_data_geo @@ -0,0 +1,104 @@ +// Permanent magnet synchronous machine +// Example of Prof. Dr. Mauricio Valencia Ferreira da Luz (Florianopolis, August 23, 2010) + +// Modified and customised for Onelab by Ruth V. Sabariego (February, 2013) + +mm = 1e-3 ; +deg2rad = Pi/180 ; + +DefineConstant[ NbrPoles = { 1, Choices {1="1", + 2="2", + 4="4", + 8="8"}, + Label "Number of poles in FE model", + Path "Input/1", Highlight "Blue", Visible 1} ] ; + +DefineConstant[ InitialRotorAngle_deg = {7.5, Label "Start rotor angle", Path "Input/20", Highlight "AliceBlue"} ]; + +//-------------------------------------------------------------------------------- + +InitialRotorAngle = InitialRotorAngle_deg*deg2rad ; // initial rotor angle, 0 if aligned + +AxialLength = 35*mm ; + +//------------------------------------------------ +//------------------------------------------------ +NbrPolesTot = 8 ; // number of poles in complete cross-section + +SymmetryFactor = NbrPolesTot/NbrPoles ; +Flag_Symmetry = (SymmetryFactor==1)?0:1 ; + +NbrSectTot = NbrPolesTot ; // number of "rotor teeth" +NbrSect = NbrSectTot*NbrPoles/NbrPolesTot ; // number of "rotor teeth" in FE model +//-------------------------------------------------------------------------------- + +//------------------------------------------------ +// Stator +//------------------------------------------------ +NbrSectTotStator = 24; // number of stator teeth +NbrSectStator = NbrSectTotStator*NbrPoles/NbrPolesTot; // number of stator teeth in FE model +//-------------------------------------------------------------------------------- + +lm = 2.352*mm ; // magnet height +Th_magnet = 32.67 *deg2rad ; // angle in degrees 0 < Th_magnet < 45 + +//-------------------------------------------------------------------------------- + +rRext = 25.6*mm; +rR1 = 10.5*mm; +rR2 = (rRext-lm); //23.243e-03; +rR3 = (rRext-0.7389*lm); //23.862e-03; +rR4 = (rRext-0.72278*lm); //23.9e-03; +rR5 = rRext; //25.6e-03; + +rS1 = 26.02*mm; +rS2 = 26.62*mm; +rS3 = 26.96*mm; +rS4 = 38.16*mm; +rS5 = 38.27*mm; +rS6 = 40.02*mm; +rS7 = 46.00*mm; + +Gap = rS1-rR5; + +rB1 = rR5+Gap/3; +rB1b = rB1; +rB2 = rR5+Gap*2/3; + + +A0 = 45 * deg2rad ; // with this choice, axis A of stator is at 30 degrees with regard to horizontal axis +A1 = 0 * deg2rad ; // Rotor initial aligned position, current position in angRot + +// ---------------------------------------------------- +// Numbers for physical regions in .geo and .pro files +// ---------------------------------------------------- +// Rotor +ROTOR_FE = 1000 ; +ROTOR_AIR = 1001 ; +ROTOR_AIRGAP = 1002 ; +ROTOR_MAGNET = 1010 ; // Index for first Magnet (1/8 model->1; full model->8) + +ROTOR_BND_MOVING_BAND = 1100 ; // Index for first line (1/8 model->1; full model->8) +ROTOR_BND_A0 = 1200 ; +ROTOR_BND_A1 = 1201 ; +SURF_INT = 1202 ; + +// Stator +STATOR_FE = 2000 ; +STATOR_AIR = 2001 ; +STATOR_AIRGAP = 2002 ; + +STATOR_BND_MOVING_BAND = 2100 ;// Index for first line (1/8 model->1; full model->8) +STATOR_BND_A0 = 2200 ; +STATOR_BND_A1 = 2201 ; + +STATOR_IND = 2300 ; //Index for first Ind (1/8 model->3; full model->24) +STATOR_IND_AP = STATOR_IND + 1 ; STATOR_IND_BM = STATOR_IND + 2 ;STATOR_IND_CP = STATOR_IND + 3 ; +STATOR_IND_AM = STATOR_IND + 4 ; STATOR_IND_BP = STATOR_IND + 5 ;STATOR_IND_CM = STATOR_IND + 6 ; + +SURF_EXT = 3000 ; // outer boundary + + +MOVING_BAND = 9999 ; + +NICEPOS = 111111 ; diff --git a/contrib/mobile/Android/res/raw/pmsm_geo b/contrib/mobile/Android/res/raw/pmsm_geo new file mode 100644 index 0000000000..efade112ec --- /dev/null +++ b/contrib/mobile/Android/res/raw/pmsm_geo @@ -0,0 +1,95 @@ +Include "pmsm_data.geo"; + +Mesh.Algorithm = 1; +Geometry.CopyMeshingMethod = 1; + +Mesh.CharacteristicLengthFactor = 1.5 ; + + +// Mesh characteristic lengths +s = 0.4 ; +pR1=(rR2-rR1)/6.*s; +pR2=(rR2-rR1)/6.*s; + +pS1=(rS7-rS1)/7.*s; +pS2=(rS7-rS1)/12.*s; +pS3=(rS6-rS3)/10.*s; + +NbrDivMB = 2*Ceil[2*Pi*rRext/8/pR1]; //1/8 Moving band + +//-------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------- + +cen = newp ; Point(cen)={0,0,0,pR1}; +nicepos_rotor[] = {}; +nicepos_stator[] = {}; + +Include "pmsm_rotor.geo"; +Include "pmsm_stator.geo"; + + +// For nice visualisation... +Mesh.Light = 0 ; +//Mesh.SurfaceFaces = 1; Mesh.SurfaceEdges=0; + +Hide { Point{ Point '*' }; } +Hide { Line{ Line '*' }; } +Show { Line{ nicepos_rotor[], nicepos_stator[] }; } + +Physical Line(NICEPOS) = { nicepos_rotor[], nicepos_stator[] }; + +//For post-processing... +View[0].Light = 0; +View[0].NbIso = 25; // Number of intervals +View[0].IntervalsType = 1; + +DefineConstant[ Flag_AddInfo = {0, Choices{0,1}, + Label "Add info about phases and axis", + Path "Input/1"} ]; + +For i In {PostProcessing.NbViews-1 : 0 : -1} + If(StrFind(View[i].Attributes, "tmp")) + Delete View[i]; + EndIf +EndFor + +If(Flag_AddInfo) + rr = 1.25 * rS3 ; + For k In {0:NbrPoles-1} + xa[] += rr*Cos(1*Pi/24+k*Pi/4) ; ya[] += rr*Sin(1*Pi/24+k*Pi/4) ; + xb[] += rr*Cos(3*Pi/24+k*Pi/4) ; yb[] += rr*Sin(3*Pi/24+k*Pi/4) ; + xc[] += rr*Cos(5*Pi/24+k*Pi/4) ; yc[] += rr*Sin(5*Pi/24+k*Pi/4) ; + EndFor + + // Adding some axes + rr0 = 0.3 * rS7 ; + rr1 = 1.3 * rS7 ; + th_d = InitialRotorAngle ; + th_q = th_d + 22.5 * deg2rad ; + + th_a = 30 * deg2rad ; + th_b = (30 + 120/4) * deg2rad ; + th_c = (30 + 240/4) * deg2rad ; + + ff = 0.9; + + xd[0] = rr0*Cos(th_d) ; yd[0] = rr0*Sin(th_d) ; + xd[1] = ff*rr1*Cos(th_d) ; yd[1] = ff*rr1*Sin(th_d) ; + xq[0] = rr0*Cos(th_q) ; yq[0] = rr0*Sin(th_q) ; + xq[1] = ff*rr1*Cos(th_q) ; yq[1] = ff*rr1*Sin(th_q) ; + + xaa[0] = rr0*Cos(th_a) ; yaa[0] = rr0*Sin(th_a) ; + xaa[1] = rr1*Cos(th_a) ; yaa[1] = rr1*Sin(th_a) ; + xbb[0] = rr0*Cos(th_b) ; ybb[0] = rr0*Sin(th_b) ; + xbb[1] = rr1*Cos(th_b) ; ybb[1] = rr1*Sin(th_b) ; + xcc[0] = rr0*Cos(th_c) ; ycc[0] = rr0*Sin(th_c) ; + xcc[1] = rr1*Cos(th_c) ; ycc[1] = rr1*Sin(th_c) ; + + + Include "info_view.geo"; + +EndIf + + + + diff --git a/contrib/mobile/Android/res/raw/pmsm_geo_pro b/contrib/mobile/Android/res/raw/pmsm_geo_pro new file mode 100644 index 0000000000..225b29dd4f --- /dev/null +++ b/contrib/mobile/Android/res/raw/pmsm_geo_pro @@ -0,0 +1,211 @@ +// +// Permanent Magnet Synchronous Generator +// + +Include "pmsm_data.geo"; + +DefineConstant[ Flag_NL = {0, + Choices{ 0="Linear", + 1="Nonlinear BH curve"}, + Label "Fe magnetic law", + Path "Input/3", Highlight "Blue"} ] ; + +DefineConstant[ Flag_SrcType_Stator = {0, + Choices{ 0="None", + 1="Current" }, + Label "Source Type in Stator", + Path "Input/4", Highlight "Blue", Visible 1} ] ; + +DefineConstant[ Flag_SrcType_Rotor = {0, + Choices{ 0="None", + 1="Current" }, + Label "Source Type in Rotor", + Path "Input/5", Highlight "Blue", Visible 0} ] ; + +DefineConstant[ Flag_Cir = {!Flag_SrcType_Stator, Choices{0,1}, + Label "Use circuit in Stator", ReadOnly 1, Visible 0} ] ; + +Group { + Stator_Fe = #STATOR_FE ; + Stator_Al = #{}; + Stator_Cu = #{}; + Stator_Air = #STATOR_AIR ; + Stator_Airgap = #STATOR_AIRGAP ; + + Stator_Bnd_A0 = #STATOR_BND_A0 ; + Stator_Bnd_A1 = #STATOR_BND_A1 ; + + Rotor_Fe = #ROTOR_FE ; + Rotor_Al = #{}; + Rotor_Cu = #{}; + Stator_Air = #STATOR_AIR ; + Stator_Airgap = #STATOR_AIRGAP ; + Stator_Bnd_MB = #STATOR_BND_MOVING_BAND ; + Stator_Bnd_A0 = #STATOR_BND_A0 ; + Stator_Bnd_A1 = #STATOR_BND_A1 ; + + Rotor_Fe = #ROTOR_FE ; + Rotor_Air = #ROTOR_AIR ; + Rotor_Airgap = #ROTOR_AIRGAP ; + + Rotor_Bnd_A0 = #ROTOR_BND_A0 ; + Rotor_Bnd_A1 = #ROTOR_BND_A1 ; + + MovingBand_PhysicalNb = #MOVING_BAND ; // Fictitious number for moving band, not in the geo file + Surf_Inf = #SURF_EXT ; + Surf_bn0 = #SURF_INT ; + Surf_cutA0 = #{STATOR_BND_A0, ROTOR_BND_A0}; + Surf_cutA1 = #{STATOR_BND_A1, ROTOR_BND_A1}; + + Dummy = #NICEPOS; + + nbMagnets = NbrPolesTot/SymmetryFactor ; + For k In {1:nbMagnets} + Rotor_Magnet~{k} = Region[ (ROTOR_MAGNET+k-1) ]; + Rotor_Magnets += Region[ Rotor_Magnet~{k} ]; + EndFor + + nbInds = (Flag_Symmetry) ? NbrPoles*NbrSectTotStator/NbrPolesTot : NbrSectTotStator ; + Printf("NbrPoles=%g, nbInds=%g SymmetryFactor=%g", NbrPoles, nbInds, SymmetryFactor); + + Stator_Ind_Ap = #{}; Stator_Ind_Am = #{STATOR_IND_AM}; + Stator_Ind_Bp = #{}; Stator_Ind_Bm = #{STATOR_IND_BM}; + Stator_Ind_Cp = #{STATOR_IND_CP}; Stator_Ind_Cm = #{}; + If(NbrPoles > 1) + Stator_Ind_Ap += #STATOR_IND_AP; + Stator_Ind_Bp += #STATOR_IND_BP; + Stator_Ind_Cm += #STATOR_IND_CM; + EndIf + + PhaseA = Region[{ Stator_Ind_Ap, Stator_Ind_Am }]; + PhaseB = Region[{ Stator_Ind_Bp, Stator_Ind_Bm }]; + PhaseC = Region[{ Stator_Ind_Cp, Stator_Ind_Cm }]; + + // Provisional: Just one physical region for nice graph in Onelab + PhaseA_pos = Region[{ Stator_Ind_Am }]; + PhaseB_pos = Region[{ Stator_Ind_Bm }]; + PhaseC_pos = Region[{ Stator_Ind_Cp }]; + + Stator_IndsP = Region[{ Stator_Ind_Ap, Stator_Ind_Bp, Stator_Ind_Cp }]; + Stator_IndsN = Region[{ Stator_Ind_Am, Stator_Ind_Bm, Stator_Ind_Cm }]; + + Stator_Inds = Region[ {PhaseA, PhaseB, PhaseC} ] ; + Rotor_Inds = Region[ {} ] ; + + StatorC = Region[{ }] ; + StatorCC = Region[{ Stator_Fe }] ; + RotorC = Region[{ }] ; + RotorCC = Region[{ Rotor_Fe, Rotor_Magnets }] ; + + // Moving band: with or without symmetry, these BND lines must be complete + Stator_Bnd_MB = #STATOR_BND_MOVING_BAND; + For k In {1:SymmetryFactor} + Rotor_Bnd_MB~{k} = Region[ (ROTOR_BND_MOVING_BAND+k-1) ]; + Rotor_Bnd_MB += Region[ Rotor_Bnd_MB~{k} ]; + EndFor + Rotor_Bnd_MBaux = Region[ {Rotor_Bnd_MB, -Rotor_Bnd_MB~{1}}]; + +} + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +Function { + + mur_fe = 1000 ; + sigma_fe = 0 ; + + NbrPhases = 3 ; + NbrPolePairs = NbrPolesTot/2 ; + + DefineConstant[ b_remanent = { 1.2, Label "Remanent induction", Path "Input/3", Highlight "AliceBlue"} ] ; + // For a radial remanent b + For k In {1:nbMagnets} + br[ Rotor_Magnet~{k} ] = (-1)^(k-1) * b_remanent * Vector[ Cos[Atan2[Y[],X[]]], Sin[Atan2[Y[],X[]]], 0 ]; + EndFor + + Inominal = 3.9 ; // Nominal current + Tnominal = 2.5 ; // Nominal torque + + //Data for modeling a stranded inductor + NbWires[] = 104 ; // Number of wires per slot + // STATOR_IND_AM comprises all the slots in that phase, we need thus to divide by the number of slots + nbSlots[] = Ceil[nbInds/NbrPhases/2] ; + SurfCoil[] = SurfaceArea[]{STATOR_IND_AM}/nbSlots[] ;//All inductors have the same surface + + FillFactor_Winding = 0.5 ; // percentage of Cu in the surface coil side, smaller than 1 + Factor_R_3DEffects = 1.5 ; // bigger than Adding 50% of resistance + + DefineConstant[ rpm = { 500, + Label "speed in rpm", + Path "Input/7", Highlight "AliceBlue"} ]; // speed in rpm + wr = rpm/60*2*Pi ; // speed in rad_mec/s + + // supply at fixed position + DefineConstant[ Freq = {wr*NbrPolePairs/(2*Pi), ReadOnly 1, + Path "Output/1", Highlight "LightYellow" } ]; + Omega = 2*Pi*Freq ; + T = 1/Freq ; + + DefineConstant[ thetaMax_deg = { 180, Label "End rotor angle (loop)", + Path "Input/21", Highlight "AliceBlue" } ]; + + theta0 = InitialRotorAngle + 0. ; + thetaMax = thetaMax_deg * deg2rad ; // end rotor angle (used in doing a loop) + + DefineConstant[ NbTurns = { (thetaMax-theta0)/(2*Pi), Label "Number of revolutions", + Path "Input/24", Highlight "LightGrey", ReadOnly 1} ]; + + DefineConstant[ delta_theta_deg = { 1., Label "step in degrees", + Path "Input/22", Highlight "AliceBlue"} ]; + + delta_theta = delta_theta_deg * deg2rad ; + + time0 = 0 ; // at initial rotor position + delta_time = delta_theta/wr; + timemax = thetaMax/wr; + + DefineConstant[ NbSteps = { Ceil[(timemax-time0)/delta_time], Label "Number of steps", + Path "Input/23", Highlight "LightGrey", ReadOnly 1} ]; + + RotorPosition[] = InitialRotorAngle + $Time * wr ; + RotorPosition_deg[] = RotorPosition[]*180/Pi; + + Flag_ParkTransformation = 1 ; + Theta_Park[] = ((RotorPosition[] + Pi/8) - Pi/6) * NbrPolePairs; // electrical degrees + Theta_Park_deg[] = Theta_Park[]*180/Pi; + + DefineConstant[ ID = { 0, Path "Input/60", Label "Id stator current", Highlight "AliceBlue"}, + IQ = { Inominal, Path "Input/61", Label "Iq stator current", Highlight "AliceBlue"}, + I0 = { 0, Visible 0} ] ; + + If(Flag_SrcType_Stator==0) + UndefineConstant["Input/60ID"]; + UndefineConstant["Input/61IQ"]; + EndIf +} + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +Dir="res/"; +ExtGmsh = ".pos"; +ExtGnuplot = ".dat"; + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +If(Flag_SrcType_Stator==1) + UndefineConstant["Input/ZR"]; +EndIf + +If(Flag_Cir) + Include "pmsm_8p_circuit.pro" ; +EndIf +Include "machine_magstadyn_a.pro" ; + +DefineConstant[ ResolutionChoices = {"TimeDomain_Loop", Path "GetDP/1"} ]; +DefineConstant[ PostOperationChoices = {"Map_LocalFields", Path "GetDP/2"} ]; +DefineConstant[ ComputeCommand = {"-solve -v 1 -v2", Path "GetDP/9"} ]; diff --git a/contrib/mobile/Android/res/raw/pmsm_pro b/contrib/mobile/Android/res/raw/pmsm_pro new file mode 100644 index 0000000000..b9ee5ce16a --- /dev/null +++ b/contrib/mobile/Android/res/raw/pmsm_pro @@ -0,0 +1,211 @@ +// +// Permanent Magnet Synchronous Generator +// + +Include "pmsm_data.geo"; + +DefineConstant[ Flag_NL = {0, + Choices{ 0="Linear", + 1="Nonlinear BH curve"}, + Label "Fe magnetic law", + Path "Input/3", Highlight "Blue"} ] ; + +DefineConstant[ Flag_SrcType_Stator = {1, + Choices{ 0="None", + 1="Current" }, + Label "Source Type in Stator", + Path "Input/4", Highlight "Blue", Visible 1} ] ; + +DefineConstant[ Flag_SrcType_Rotor = {0, + Choices{ 0="None", + 1="Current" }, + Label "Source Type in Rotor", + Path "Input/5", Highlight "Blue", Visible 0} ] ; + +DefineConstant[ Flag_Cir = {!Flag_SrcType_Stator, Choices{0,1}, + Label "Use circuit in Stator", ReadOnly 1, Visible 0} ] ; + +Group { + Stator_Fe = #STATOR_FE ; + Stator_Al = #{}; + Stator_Cu = #{}; + Stator_Air = #STATOR_AIR ; + Stator_Airgap = #STATOR_AIRGAP ; + + Stator_Bnd_A0 = #STATOR_BND_A0 ; + Stator_Bnd_A1 = #STATOR_BND_A1 ; + + Rotor_Fe = #ROTOR_FE ; + Rotor_Al = #{}; + Rotor_Cu = #{}; + Stator_Air = #STATOR_AIR ; + Stator_Airgap = #STATOR_AIRGAP ; + Stator_Bnd_MB = #STATOR_BND_MOVING_BAND ; + Stator_Bnd_A0 = #STATOR_BND_A0 ; + Stator_Bnd_A1 = #STATOR_BND_A1 ; + + Rotor_Fe = #ROTOR_FE ; + Rotor_Air = #ROTOR_AIR ; + Rotor_Airgap = #ROTOR_AIRGAP ; + + Rotor_Bnd_A0 = #ROTOR_BND_A0 ; + Rotor_Bnd_A1 = #ROTOR_BND_A1 ; + + MovingBand_PhysicalNb = #MOVING_BAND ; // Fictitious number for moving band, not in the geo file + Surf_Inf = #SURF_EXT ; + Surf_bn0 = #SURF_INT ; + Surf_cutA0 = #{STATOR_BND_A0, ROTOR_BND_A0}; + Surf_cutA1 = #{STATOR_BND_A1, ROTOR_BND_A1}; + + Dummy = #NICEPOS; + + nbMagnets = NbrPolesTot/SymmetryFactor ; + For k In {1:nbMagnets} + Rotor_Magnet~{k} = Region[ (ROTOR_MAGNET+k-1) ]; + Rotor_Magnets += Region[ Rotor_Magnet~{k} ]; + EndFor + + nbInds = (Flag_Symmetry) ? NbrPoles*NbrSectTotStator/NbrPolesTot : NbrSectTotStator ; + Printf("NbrPoles=%g, nbInds=%g SymmetryFactor=%g", NbrPoles, nbInds, SymmetryFactor); + + Stator_Ind_Ap = #{}; Stator_Ind_Am = #{STATOR_IND_AM}; + Stator_Ind_Bp = #{}; Stator_Ind_Bm = #{STATOR_IND_BM}; + Stator_Ind_Cp = #{STATOR_IND_CP}; Stator_Ind_Cm = #{}; + If(NbrPoles > 1) + Stator_Ind_Ap += #STATOR_IND_AP; + Stator_Ind_Bp += #STATOR_IND_BP; + Stator_Ind_Cm += #STATOR_IND_CM; + EndIf + + PhaseA = Region[{ Stator_Ind_Ap, Stator_Ind_Am }]; + PhaseB = Region[{ Stator_Ind_Bp, Stator_Ind_Bm }]; + PhaseC = Region[{ Stator_Ind_Cp, Stator_Ind_Cm }]; + + // Provisional: Just one physical region for nice graph in Onelab + PhaseA_pos = Region[{ Stator_Ind_Am }]; + PhaseB_pos = Region[{ Stator_Ind_Bm }]; + PhaseC_pos = Region[{ Stator_Ind_Cp }]; + + Stator_IndsP = Region[{ Stator_Ind_Ap, Stator_Ind_Bp, Stator_Ind_Cp }]; + Stator_IndsN = Region[{ Stator_Ind_Am, Stator_Ind_Bm, Stator_Ind_Cm }]; + + Stator_Inds = Region[ {PhaseA, PhaseB, PhaseC} ] ; + Rotor_Inds = Region[ {} ] ; + + StatorC = Region[{ }] ; + StatorCC = Region[{ Stator_Fe }] ; + RotorC = Region[{ }] ; + RotorCC = Region[{ Rotor_Fe, Rotor_Magnets }] ; + + // Moving band: with or without symmetry, these BND lines must be complete + Stator_Bnd_MB = #STATOR_BND_MOVING_BAND; + For k In {1:SymmetryFactor} + Rotor_Bnd_MB~{k} = Region[ (ROTOR_BND_MOVING_BAND+k-1) ]; + Rotor_Bnd_MB += Region[ Rotor_Bnd_MB~{k} ]; + EndFor + Rotor_Bnd_MBaux = Region[ {Rotor_Bnd_MB, -Rotor_Bnd_MB~{1}}]; + +} + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +Function { + + mur_fe = 1000 ; + sigma_fe = 0 ; + + NbrPhases = 3 ; + NbrPolePairs = NbrPolesTot/2 ; + + DefineConstant[ b_remanent = { 1.2, Label "Remanent induction", Path "Input/3", Highlight "AliceBlue"} ] ; + // For a radial remanent b + For k In {1:nbMagnets} + br[ Rotor_Magnet~{k} ] = (-1)^(k-1) * b_remanent * Vector[ Cos[Atan2[Y[],X[]]], Sin[Atan2[Y[],X[]]], 0 ]; + EndFor + + Inominal = 3.9 ; // Nominal current + Tnominal = 2.5 ; // Nominal torque + + //Data for modeling a stranded inductor + NbWires[] = 104 ; // Number of wires per slot + // STATOR_IND_AM comprises all the slots in that phase, we need thus to divide by the number of slots + nbSlots[] = Ceil[nbInds/NbrPhases/2] ; + SurfCoil[] = SurfaceArea[]{STATOR_IND_AM}/nbSlots[] ;//All inductors have the same surface + + FillFactor_Winding = 0.5 ; // percentage of Cu in the surface coil side, smaller than 1 + Factor_R_3DEffects = 1.5 ; // bigger than Adding 50% of resistance + + DefineConstant[ rpm = { 500, + Label "speed in rpm", + Path "Input/7", Highlight "AliceBlue"} ]; // speed in rpm + wr = rpm/60*2*Pi ; // speed in rad_mec/s + + // supply at fixed position + DefineConstant[ Freq = {wr*NbrPolePairs/(2*Pi), ReadOnly 1, + Path "Output/1", Highlight "LightYellow" } ]; + Omega = 2*Pi*Freq ; + T = 1/Freq ; + + DefineConstant[ thetaMax_deg = { 180, Label "End rotor angle (loop)", + Path "Input/21", Highlight "AliceBlue" } ]; + + theta0 = InitialRotorAngle + 0. ; + thetaMax = thetaMax_deg * deg2rad ; // end rotor angle (used in doing a loop) + + DefineConstant[ NbTurns = { (thetaMax-theta0)/(2*Pi), Label "Number of revolutions", + Path "Input/24", Highlight "LightGrey", ReadOnly 1} ]; + + DefineConstant[ delta_theta_deg = { 1., Label "step in degrees", + Path "Input/22", Highlight "AliceBlue"} ]; + + delta_theta = delta_theta_deg * deg2rad ; + + time0 = 0 ; // at initial rotor position + delta_time = delta_theta/wr; + timemax = thetaMax/wr; + + DefineConstant[ NbSteps = { Ceil[(timemax-time0)/delta_time], Label "Number of steps", + Path "Input/23", Highlight "LightGrey", ReadOnly 1} ]; + + RotorPosition[] = InitialRotorAngle + $Time * wr ; + RotorPosition_deg[] = RotorPosition[]*180/Pi; + + Flag_ParkTransformation = 1 ; + Theta_Park[] = ((RotorPosition[] + Pi/8) - Pi/6) * NbrPolePairs; // electrical degrees + Theta_Park_deg[] = Theta_Park[]*180/Pi; + + DefineConstant[ ID = { 0, Path "Input/60", Label "Id stator current", Highlight "AliceBlue"}, + IQ = { Inominal, Path "Input/61", Label "Iq stator current", Highlight "AliceBlue"}, + I0 = { 0, Visible 0} ] ; + + If(Flag_SrcType_Stator==0) + UndefineConstant["Input/60ID"]; + UndefineConstant["Input/61IQ"]; + EndIf +} + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +Dir="res/"; +ExtGmsh = ".pos"; +ExtGnuplot = ".dat"; + +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- +// -------------------------------------------------------------------------- + +If(Flag_SrcType_Stator==1) + UndefineConstant["Input/ZR"]; +EndIf + +If(Flag_Cir) + Include "pmsm_8p_circuit.pro" ; +EndIf +Include "machine_magstadyn_a.pro" ; + +DefineConstant[ ResolutionChoices = {"TimeDomain_Loop", Path "GetDP/1"} ]; +DefineConstant[ PostOperationChoices = {"Map_LocalFields", Path "GetDP/2"} ]; +DefineConstant[ ComputeCommand = {"-solve -v 1 -v2", Path "GetDP/9"} ]; diff --git a/contrib/mobile/Android/res/raw/pmsm_rotor_geo b/contrib/mobile/Android/res/raw/pmsm_rotor_geo new file mode 100644 index 0000000000..c051cf1a6d --- /dev/null +++ b/contrib/mobile/Android/res/raw/pmsm_rotor_geo @@ -0,0 +1,163 @@ +//-------------------------------------------------------------------------------- +// Rotor PMSM +//-------------------------------------------------------------------------------- +A = InitialRotorAngle-45/2*deg2rad + A1; // with Theta_Park + +sinA = Sin(A); cosA = Cos(A); +pntR[]+=newp; Point(newp)={rR1*cosA, rR1*sinA, 0, pR1}; +pntR[]+=newp; Point(newp)={rR2*cosA, rR2*sinA, 0, pR1}; +pntR[]+=newp; Point(newp)={rR4*cosA, rR4*sinA, 0, pR1}; +pntR[]+=newp; Point(newp)={rR5*cosA, rR5*sinA, 0, pR1}; +pntR[]+=newp; Point(newp)={rB1*cosA, rB1*sinA, 0, pR2}; + +For k In {0:#pntR[]-2} + linR0[]+=newl; Line(newl) = {pntR[k], pntR[k+1]}; +EndFor + +Transfinite Line{linR0[0]} = Ceil[(rR2-rR1)/pR1] ; +Transfinite Line{linR0[1]} = Ceil[(rR4-rR2)/pR1] ; +Transfinite Line{linR0[2]} = Ceil[(rR5-rR4)/pR1] ; +Transfinite Line{linR0[3]} = Ceil[(rB1-rR5)/pR1] ; + +For k In {0:#linR0[]-1} + linR1[] += Rotate {{0, 0, 1}, {0, 0, 0}, A0+A1} { Duplicata{Line{linR0[k]};} }; +EndFor + +AA[] = {(A0-Th_magnet)/2+A1, Th_magnet, (A0-Th_magnet)/2+A1} ; + +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, AA[0]} { Point{pntR[0]}; }; +cirR[]+=lin[1]; +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, AA[1]} { Point{lin[0]}; }; +cirR[]+=lin[1]; +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, AA[2]} { Point{lin[0]}; }; +cirR[]+=lin[1]; + +surfint[]=cirR[{0,1,2}] ; // boundary conditions + +pMagnet[] = Rotate {{0, 0, 1}, {0, 0, 0}, AA[0]} { Duplicata{Point{pntR[1]};} }; +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, AA[1]} { Point{pMagnet[0]}; }; +pMagnet[] += lin[0]; +cirR[] += lin[1] ; + +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, AA[0]} { Point{pntR[2]}; }; +cirR[]+=lin[1]; pMagnet[] += lin[0]; +pMagnet[] += Rotate {{0, 0, 1}, {0, 0, 0}, AA[1]} { Duplicata{Point{lin[0]};} }; +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, AA[2]} { Point{pMagnet[3]}; }; +cirR[]+=lin[1]; + +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, AA[0]} { Point{pntR[3]}; }; +cirR[]+=lin[1]; +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, AA[1]} { Point{lin[0]}; }; +cirR[]+=lin[1]; +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, AA[2]} { Point{lin[0]}; }; +cirR[]+=lin[1]; + +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, A0+A1} { Point{pntR[4]}; }; +cirR[]+=lin[1]; + +linR2[] = Rotate {{0, 0, 1}, {0, 0, 0}, (A0-Th_magnet)/2+A1} { Duplicata{Line{linR0[{1,2}]};} }; +linR3[] = Rotate {{0, 0, 1}, {0, 0, 0},-(A0-Th_magnet)/2+A1} { Duplicata{Line{linR1[{1,2}]};} }; + +// surfaces rotor +Line Loop(newll) = {linR0[{0,1}], cirR[4], -linR2[0], cirR[3], linR3[0], cirR[5], -linR1[{1,0}], -cirR[{2,1,0}]}; +srotor[0]=news; Plane Surface(srotor[0]) = {newll-1}; + +Line Loop(newl) = {linR2[1], cirR[7], -linR3[{1,0}], -cirR[3], linR2[0]}; +smagnet[0]=news; Plane Surface(smagnet[0]) = {newll-1}; + +nn = #cirR[]-1 ; +Line Loop(newll) = {cirR[{nn-5}], linR2[1], -cirR[{nn-3}], -linR0[2]}; +sairrotor[]+=news; Plane Surface(news) = {newll-1}; +Line Loop(newll) = {cirR[{nn-4}], linR1[2], -cirR[{nn-1}], -linR3[1]}; +sairrotor[]+=news; Plane Surface(news) = {newll-1}; + +Line Loop(newll) = {linR0[3], cirR[nn], -linR1[3], -cirR[{nn-1:nn-3:-1}]}; +sairrotormb[]+=news; Plane Surface(news) = {newll-1}; + +// ------------------------------------------------------------------------------- +// Moving band == AirGap rotor side +// ------------------------------------------------------------------------------- +Transfinite Line{cirR[nn]} = NbrDivMB+1 ; + +//Filling the gap for the whole 2*Pi +lineMBrotor[]=cirR[{nn}]; +For k In {1:NbrPolesTot-1} + lineMBrotoraux[]+=Rotate {{0, 0, 1}, {0, 0, 0}, k*A0} { Duplicata{Line{lineMBrotor[]};} }; +EndFor + +// ------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- +If(SymmetryFactor<8) +// FULL MODEL ==> Rotation of NbrPolesTot*Pi/4 +// For simplicity: rotating first the interior and exterior boundaries + + If (SymmetryFactor>1) + For k In {0:#linR1[]-1} + linR1_[] += Rotate {{0, 0, 1}, {0, 0, 0}, 2*Pi/SymmetryFactor-Pi/4} { Duplicata{Line{linR1[k]};} }; + EndFor + linR1[] = linR1_[]; + EndIf + + For k In {1:NbrPoles-1} + surfint[] += Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Line{surfint[{0:2}]};} }; + EndFor + For k In {1:NbrPoles-1} + srotor[] += Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Surface{srotor[0]};} }; + smagnet[]+= Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Surface{smagnet[0]};} }; + sairrotor[] += Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Surface{sairrotor[{0,1}]};} }; + sairrotormb[]+= Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Surface{sairrotormb[0]};} }; + EndFor +EndIf + + +// ------------------------------------------------------------------------------- +// Physical regions +// ------------------------------------------------------------------------------- + +Physical Surface(ROTOR_FE) = {srotor[]}; // Rotor +Physical Surface(ROTOR_AIR) = {sairrotor[]}; // AirRotor +Physical Surface(ROTOR_AIRGAP) = {sairrotormb[]};// AirRotor for possible torque computation with Maxwell stress tensor + +NN = (Flag_Symmetry)?NbrPoles:NbrPolesTot; +For k In {0:NN-1} + Physical Surface(ROTOR_MAGNET+k) = {smagnet[k]}; // Magnets +EndFor + +Physical Line(SURF_INT) = {surfint[]}; // SurfInt + + +If(Flag_Symmetry) //Lines for symmetry link + Physical Line(ROTOR_BND_A0) = linR0[]; + Physical Line(ROTOR_BND_A1) = linR1[]; +EndIf + +lineMBrotor[] += lineMBrotoraux[] ; +If(!Flag_Symmetry) + Physical Line(ROTOR_BND_MOVING_BAND) = {lineMBrotor[]}; +EndIf +If(Flag_Symmetry) + nr = #lineMBrotor[]; + nnp = nr/(NbrPolesTot/NbrSect) ; + For k In {1:Floor[NbrPolesTot/NbrSect]} + kk= ((k*nnp-1) > nr) ? nr-1 : k*nnp-1 ; + Physical Line(ROTOR_BND_MOVING_BAND+k-1) = lineMBrotor[{(k-1)*nnp:kk}] ; + EndFor + k1 = Floor[NbrPolesTot/NbrSect]; + k2 = Ceil[NbrPolesTot/NbrSect]; + If (k2 > k1) + Physical Line(ROTOR_BND_MOVING_BAND+k2-1) = lineMBrotor[{(k2-1)*nnp:#lineMBrotor[]-1}] ; + EndIf +EndIf + +// For nice visualisation... +linRotor[] = CombinedBoundary{Surface{srotor[]};}; +linMagnet[] = Boundary{Surface{smagnet[]};}; + +nicepos_rotor[] += { linRotor[], linMagnet[] }; + +Color SteelBlue {Surface{srotor[]};} +Color SkyBlue {Surface{sairrotor[], sairrotormb[]};} +Color Orchid {Surface{smagnet[{0:#smagnet[]-1:2}]};} +If(#smagnet[]>1) +Color Purple {Surface{smagnet[{1:#smagnet[]-1:2}]};} +EndIf diff --git a/contrib/mobile/Android/res/raw/pmsm_stator_geo b/contrib/mobile/Android/res/raw/pmsm_stator_geo new file mode 100644 index 0000000000..e928a4a055 --- /dev/null +++ b/contrib/mobile/Android/res/raw/pmsm_stator_geo @@ -0,0 +1,215 @@ +// ------------------------------------------------------------------------------- +// Moving band == AirGap stator side +// ------------------------------------------------------------------------------- +pntG[]+=newp; Point(newp) = {rB2, 0., 0., pS1}; // aligned with the stator +circ[] = Extrude {{0, 0, 1}, {0, 0, 0}, A0} { Point{pntG[0]}; }; +pntG[]+=circ[0]; +lineMBstator[]=circ[1]; +Transfinite Line{lineMBstator[0]} = NbrDivMB+1 ; + +//Filling the gap for the whole 2*Pi +For k In {1:NbrPolesTot-1} + lineMBstatoraux[]+= Rotate {{0, 0, 1}, {0, 0, 0}, k*A0} { Duplicata{Line{lineMBstator[0]};} }; +EndFor + +// ------------------------------------------------------------------------------- +// Stator +// ------------------------------------------------------------------------------- + +pntS[] = newp; Point(newp)={rS1, 0, 0, pS1}; +linS[] = newl; Line(newl) = {pntG[0], pntS[0]}; +linS[]+= Rotate {{0, 0, 1}, {0, 0, 0}, A0} { Duplicata{Line{linS[0]};} }; + +pntS[]+=newp; Point(newp)={rS7,0,0,pS2}; +points[]=Boundary{Line{linS[1]};}; +pntS[]+=points[1]; + +lin[] = Extrude {{0, 0, 1}, {0, 0, 0}, A0} { Point{pntS[1]}; }; +cirS[]= lin[1]; pntS[]+=lin[0]; + +linS[]+=newl; Line(newl) = {pntS[0], pntS[1]}; +linS[]+=newl; Line(newl) = {pntS[2], pntS[3]}; + +// ------------------------------------------------------------------------------- +// Slots +// ------------------------------------------------------------------------------- + +A2 = 0.0; +AA[]=deg2rad*{2.77+A2, 4.0+A2, 5.52+A2, 5.56+A2, 5.65+A2, 9.35+A2, 9.44+A2, 9.48+A2, 11+A2, 12.23+A2} ; + +For k In {0:#AA[]-1} + cosAA[]+=Cos(AA[k]); sinAA[]+=Sin(AA[k]); +EndFor + +pntSlot[]+=newp; Point(newp)={rS5*cosAA[0], rS5*sinAA[0], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS3*cosAA[1], rS3*sinAA[1], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS1*cosAA[2], rS1*sinAA[2], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS2*cosAA[3], rS2*sinAA[3], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS4*cosAA[3], rS4*sinAA[3], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS6*cosAA[4], rS6*sinAA[4], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS6*cosAA[5], rS6*sinAA[5], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS4*cosAA[6], rS4*sinAA[6], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS2*cosAA[6], rS2*sinAA[6], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS1*cosAA[7], rS1*sinAA[7], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS3*cosAA[8], rS3*sinAA[8], 0., pS3}; +pntSlot[]+=newp; Point(newp)={rS5*cosAA[9], rS5*sinAA[9], 0., pS3}; + +// air slot 1 +linASlot[]+=newl ; Line(newl)={pntSlot[2], pntSlot[3]}; +linASlot[]+=newl ; Line(newl)={pntSlot[3], pntSlot[1]}; +linASlot[]+=newl ; Circle(newl)={pntSlot[1], cen, pntSlot[10]}; +linASlot[]+=newl ; Line(newl)={pntSlot[10], pntSlot[8]}; +linASlot[]+=newl ; Line(newl)={pntSlot[8], pntSlot[9]}; +linASlot[]+=newl ; Circle(newl)={pntSlot[9], cen, pntSlot[2]}; + +Line Loop(newll) = {linASlot[]}; +sairslot[] += news ; Plane Surface(sairslot[0]) = {newll-1}; + +// coil slot 1 +linSlot[]+=newl ; Line(newl)={pntSlot[1], pntSlot[0]}; +linSlot[]+=newl ; Circle(newl)= {pntSlot[0], pntSlot[4], pntSlot[5]}; +linSlot[]+=newl ; Line(newl)={pntSlot[5], pntSlot[6]}; +linSlot[]+=newl ; Circle(newl)={pntSlot[6], pntSlot[7],pntSlot[11]}; +linSlot[]+=newl ; Line(newl)={pntSlot[11], pntSlot[10]}; + +Line Loop(newll) = {-linASlot[2],linSlot[]}; +sslot[] += news ; Plane Surface(sslot[0]) = {newll-1}; + +// slots 2 and 3 +A2 = 15*deg2rad; + +pntSlot0[0] = pntSlot[2]; +pntSlot1[0] = pntSlot[9]; +For k In{1:2} + pntSlot0[] += Rotate {{0, 0, 1}, {0, 0, 0}, A2} { Duplicata{Point{pntSlot0[k-1]};} }; + pntSlot1[] += Rotate {{0, 0, 1}, {0, 0, 0}, A2} { Duplicata{Point{pntSlot1[k-1]};} }; +EndFor + +For k In{1:2} + sslot[] += Rotate {{0, 0, 1}, {0, 0, 0}, A2} { Duplicata{Surface{sslot[k-1]};} }; + sairslot[] += Rotate {{0, 0, 1}, {0, 0, 0}, A2} { Duplicata{Surface{sairslot[k-1]};} }; +EndFor + +cSlot[]+=newl; Circle(newl) = {pntS[0], cen, pntSlot[2]}; +cSlot[]+=newl; Circle(newl) = {pntSlot1[0], cen, pntSlot0[1]}; +cSlot[]+=newl; Circle(newl) = {pntSlot1[1], cen, pntSlot0[2]}; +cSlot[]+=newl; Circle(newl) = {pntSlot1[2], cen, pntS[2]}; + +linesslot0[] = CombinedBoundary{ Surface{ sslot[0], sairslot[0] } ;}; +linesslot1[] = CombinedBoundary{ Surface{ sslot[1], sairslot[1] } ;}; +linesslot2[] = CombinedBoundary{ Surface{ sslot[2], sairslot[2] } ;}; + +Line Loop(newll) = {-lineMBstator[0],linS[0], cSlot[0],-linesslot0[{4}], + cSlot[1],-linesslot1[{9}], + cSlot[2],-linesslot2[{9}], cSlot[3], -linS[1]}; +sairgapS[0]=news; Plane Surface(sairgapS[0]) = {newll-1}; + +linesslot0[] -= linesslot0[{4}]; +linesslot1[] -= linesslot1[{9}]; +linesslot2[] -= linesslot2[{9}]; +Line Loop(newll) = { cSlot[0], linesslot0[], + cSlot[1], linesslot1[], + cSlot[2], linesslot2[], + cSlot[3], linS[3], -cirS[0], -linS[2]}; +sstator[0]=news; Plane Surface(sstator[0]) = {newll-1}; + +// ------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- + +auxlink[]=linS[{1,3}]; // A1 + +If(SymmetryFactor<8) + // FULL MODEL ==> Rotation of NbrPolesTot*Pi/4 + // For simplicity: rotating the interior and exterior boundaries + + If (SymmetryFactor>1) + For k In {0:#auxlink[]-1} + auxlink_[] += Rotate {{0, 0, 1}, {0, 0, 0}, 2*Pi/SymmetryFactor-Pi/4} { Duplicata{Line{auxlink[k]};} }; + EndFor + auxlink[] = auxlink_[]; + EndIf + + For k In {1:NbrPoles-1} + cirS[] += Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Line{cirS[{0}]};} }; + EndFor + For k In {1:NbrPoles-1} + sstator[]+= Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Surface{sstator[0]};} }; + sairgapS[]+= Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Surface{sairgapS[0]};} }; + sairslot[]+= Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Surface{sairslot[{0:2}]};} }; + sslot[]+= Rotate {{0, 0, 1}, {0, 0, 0}, k*Pi/4} { Duplicata{ Surface{sslot[{0:2}]};} }; + EndFor +EndIf + + + +// ------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- +// Physical regions +// ------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- + +Physical Surface(STATOR_FE) = {sstator[]}; // Stator +Physical Surface(STATOR_AIR) = {sairslot[]}; // AirStator +Physical Surface(STATOR_AIRGAP) = {sairgapS[]}; // AirStator for possible torque computation with Maxwell stress tensor + +NN = (Flag_Symmetry)?NbrSectStator:NbrSectTotStator; +//For k In {0:NN-1} +// Physical Surface(STATOR_IND+k) = {sslot[k]}; //Inds +//EndFor + +Physical Surface(STATOR_IND_AM) = {sslot[{0:NN-1:6}]}; +Physical Surface(STATOR_IND_CP) = {sslot[{1:NN-1:6}]}; +Physical Surface(STATOR_IND_BM) = {sslot[{2:NN-1:6}]}; +If(NbrSectStator>2) + Physical Surface(STATOR_IND_AP) = {sslot[{3:NN-1:6}]}; + Physical Surface(STATOR_IND_CM) = {sslot[{4:NN-1:6}]}; + Physical Surface(STATOR_IND_BP) = {sslot[{5:NN-1:6}]}; +EndIf + +Color Pink {Surface{ sslot[{0:NN-1:6}] };} // A- +Color ForestGreen {Surface{ sslot[{1:NN-1:6}] };} // C+ +Color PaleGoldenrod{Surface{ sslot[{2:NN-1:6}] };} // B- +If (#sslot[]>=6) +Color Red {Surface{ sslot[{3:NN-1:6}] };} // A+ +Color SpringGreen{Surface{ sslot[{4:NN-1:6}] };} // C- +Color Gold {Surface{ sslot[{5:NN-1:6}] };} // B+ +EndIf + + +Physical Line(SURF_EXT) = {cirS[]}; // SurfExt + +If(Flag_Symmetry) //Lines for symmetry link + Physical Line(STATOR_BND_A0) = linS[{0,2}]; + Physical Line(STATOR_BND_A1) = auxlink[] ; +EndIf + + +lineMBstator[] += lineMBstatoraux[] ; +If(!Flag_Symmetry) + Physical Line(STATOR_BND_MOVING_BAND) = {lineMBstator[]}; +EndIf +If(Flag_Symmetry) +ns = #lineMBstator[]; +nns = ns/SymmetryFactor ; +For k In {1:SymmetryFactor} + kk= ((k*nns-1) > ns) ? ns-1 : k*nns-1 ; + Physical Line(STATOR_BND_MOVING_BAND+k-1) = {lineMBstator[{(k-1)*nns:kk}]}; +EndFor + k1 = Floor[NbrPolesTot/NbrSect]; + k2 = Ceil[NbrPolesTot/NbrSect]; + If (k2 > k1) + Physical Line(STATOR_BND_MOVING_BAND+k2-1) = lineMBstator[{(k2-1)*nns:#lineMBstator[]-1}] ; + EndIf +EndIf + + +// For nice visualisation... +linStator[] = CombinedBoundary{Surface{sstator[]};}; +linSlot[] = CombinedBoundary{Surface{sslot[]};}; + +nicepos_stator[] += {linStator[],linSlot[] }; + +Color SteelBlue {Surface{sstator[]};} +Color SkyBlue {Surface{sairslot[],sairgapS[]};} + + diff --git a/contrib/mobile/Android/res/raw/test_geo b/contrib/mobile/Android/res/raw/test_geo new file mode 100644 index 0000000000..d60f76efbb --- /dev/null +++ b/contrib/mobile/Android/res/raw/test_geo @@ -0,0 +1,64 @@ +Point(1) = {0,0,0}; + +DefineConstant +[ + n0 = {3, + Label "Number", + Path "Test widgets/Numbers"} + n01 = {3, Min 1, Max 4, Step 1, + Label "Number (with range)", + Path "Test widgets/Numbers"} + n1 = {3, ReadOnly 1, + Label "Number (read only)", + Path "Test widgets/Numbers"} + n12 = {3, ReadOnlyRange 1, Min 1, Max 4, Step 1, + Label "Number (read only range)", + Path "Test widgets/Numbers"} + n2 = {3, Choices{1, 2, 3, 4}, + Label "Number (with choices)", + Path "Test widgets/Numbers"} + n3 = {1, Choices{0,1}, + Label "Number (with binary choice) - Show String Options?", + Path "Test widgets/Numbers"}, + n4 = {3, Choices{1 = "One", + 2 = "Two", + 3 = "Three", + 4 = "Go!!"}, + Label "Number (with enumeration)", + Path "Test widgets/Numbers"} +]; + +Printf("N3 = %g", n3); + +If(n3) // test define/undefine +Printf("N3 IS SET"); +DefineConstant[ + s0 = {"a", + Label "String", + Path "Test widgets/Strings"} + s1 = {"a", ReadOnly 1, + Label "String (read only)", + Path "Test widgets/Strings"} + s2 = {"a", Choices {"a","b","c"}, + Label "String with choices", + Path "Test widgets/Strings"} + s20 = {"a, c", Choices {"a","b","c"}, MultipleSelection "101", + Label "String with multiple selection", + Path "Test widgets/Strings"} + s3 = {"a.txt", Choices{"a.txt","b.txt","c.txt"}, Kind "file", + Label "File", + Path "Test widgets/Strings"} + s4 = {"a.txt", Kind "file", Macro "Gmsh", + Label "Macro", + Path "Test widgets/Strings"} +]; +EndIf +If(!n3) + Printf("N3 IS **NOT** SET"); +UndefineConstant[ "Test widgets/Strings/s0", + "Test widgets/Strings/s1", + "Test widgets/Strings/s2", + "Test widgets/Strings/s20", + "Test widgets/Strings/s3", + "Test widgets/Strings/s4"]; +EndIf diff --git a/contrib/mobile/Android/res/values-v11/styles.xml b/contrib/mobile/Android/res/values-v11/styles.xml new file mode 100644 index 0000000000..d408cbc37a --- /dev/null +++ b/contrib/mobile/Android/res/values-v11/styles.xml @@ -0,0 +1,5 @@ +<resources> + + <style name="AppTheme" parent="android:Theme.Holo.Light" /> + +</resources> \ No newline at end of file diff --git a/contrib/mobile/Android/res/values-v14/styles.xml b/contrib/mobile/Android/res/values-v14/styles.xml new file mode 100644 index 0000000000..1c089a788c --- /dev/null +++ b/contrib/mobile/Android/res/values-v14/styles.xml @@ -0,0 +1,5 @@ +<resources> + + <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" /> + +</resources> \ No newline at end of file diff --git a/contrib/mobile/Android/res/values/strings.xml b/contrib/mobile/Android/res/values/strings.xml new file mode 100644 index 0000000000..eaf9831ea8 --- /dev/null +++ b/contrib/mobile/Android/res/values/strings.xml @@ -0,0 +1,25 @@ +<resources> + + <string name="app_name">Onelab</string> + <string name="button_open_external_file">Open MSH file on external storage</string> + <string name="button_ok">OK</string> + <string name="button_recalculate_param">Recalulate with new parameters</string> + <string name="dialog_title_choosefile">Choose a MSH file</string> + <string name="error_nosdcard">No SDcard found on your device</string> + <string name="title_parameter">Settings</string> + <string name="title_activity_main">Onelab</string> + <string name="error_nomshfile">No compatible files or directories in this folder</string> + <string name="menu_list">Load a model</string> + <string name="menu_settings">Settings</string> + <string name="menu_model">Show the model</string> + <string name="menu_postpro">Post-processing</string> + <string name="menu_hidebar">Hide the top bar</string> + <string name="menu_showbar">Show the top bar</string> + <string name="menu_view">Change the view</string> + <string name="menu_view_x">Set X view</string> + <string name="menu_view_y">Set Y view</string> + <string name="menu_view_z">Set Z view</string> + <string name="menu_view_scale">Reset unit scale</string> + <string name="menu_view_translation">Center the model</string> + +</resources> \ No newline at end of file diff --git a/contrib/mobile/Android/res/values/styles.xml b/contrib/mobile/Android/res/values/styles.xml new file mode 100644 index 0000000000..4dba0d0a4c --- /dev/null +++ b/contrib/mobile/Android/res/values/styles.xml @@ -0,0 +1,5 @@ +<resources> + + <style name="AppTheme" parent="android:Theme.Light" /> + +</resources> \ No newline at end of file diff --git a/contrib/mobile/Android/res/xml/models.xml b/contrib/mobile/Android/res/xml/models.xml new file mode 100644 index 0000000000..80b25aa292 --- /dev/null +++ b/contrib/mobile/Android/res/xml/models.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> + +<models> + <model> + <title>Magnet</title> + <summary>Simple magnet example</summary> + <file type="geo">magnet.geo</file> + </model> + + <model> + <title>Eight-pole permanent magnet synchronous machine</title> + <summary></summary> + <file type="geo">pmsm.geo</file> + </model> + + <model> + <title>Test</title> + <summary>test all parameters of onelab</summary> + <file type="geo">test.geo</file> + </model> +</models> diff --git a/contrib/mobile/Android/src/org/geuz/onelab/GLESRender.java b/contrib/mobile/Android/src/org/geuz/onelab/GLESRender.java new file mode 100644 index 0000000000..2cb182e27f --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/GLESRender.java @@ -0,0 +1,45 @@ +package org.geuz.onelab; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView.Renderer; +import android.os.Handler; + +public class GLESRender implements Renderer{ + + Gmsh mGModel; + Handler loadingHand; + + public GLESRender(Gmsh model) { + this.mGModel = model; + } + + public void load(String filename){ + mGModel.load(filename); + } + + public void translate(float tx, float ty, float tz){ + mGModel.translation(tx, ty, tz); + } + public void scale(float sx, float sy, float sz){ + mGModel.scale(sx, sy, sz); + } + public void rotate(float rx, float ry, float rz){ + mGModel.rotate(rx, ry, rz); + } + + // OpenGL ES methods + public void onDrawFrame(GL10 gl) { + mGModel.viewDraw(); + } + + public void onSurfaceChanged(GL10 gl, int width, int height) { + mGModel.viewInit(width, height); + } + + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + + } + +} diff --git a/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java b/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java new file mode 100644 index 0000000000..f13d71f968 --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java @@ -0,0 +1,90 @@ +package org.geuz.onelab; + +import android.os.Handler; + +public class Gmsh { + /** From C / C++ code **/ + static { + System.loadLibrary("f2cblas"); + System.loadLibrary("f2clapack"); + System.loadLibrary("petsc"); + System.loadLibrary("Gmsh"); + System.loadLibrary("GetDP"); + System.loadLibrary("Onelab"); + + } + private native long init(String name); // Init Gmsh + private native void loadFile(long ptr, String name); // load a file(OpenProjet) + private native void initView(long ptr, int w, int h); // Called each time the GLView change + private native void drawView(long ptr); // Called each time the GLView request a render + private native void setTranslation(long ptr, float tx, float ty, float tz); // translate the current GModel + private native void setScale(long ptr, float sx, float sy, float sz); // scale the current GModel + private native void setRotate(long ptr, float rx, float ry, float rz); // rotate the current GModel + private native void setShow(long ptr, String what, boolean show); // select what to show / hide + private native long getOnelabInstance(); // return the singleton of the onelab server + public native String[] getParams(); // return the parameters for onelab + public native int setParam(String type, String name, String value); // change a parameters + public native String[] getPView(); // get a list of PViews + public native void setPView(int position, int intervalsType,int visible,int nbIso); // Change options for a PView + public native int onelabCB(String action); // Call onelab + + /** Java CLASS **/ + private long ptr; + private long onelab; + private Handler handler; + + public Gmsh(String name, Handler handler) { + ptr = this.init(name); + onelab = this.getOnelabInstance(); + this.handler = handler; + } + + public void viewInit(int w, int h) { + this.initView(ptr, w, h); + } + + public void viewDraw() { + this.drawView(ptr); + } + + public void load(String filename){ + this.loadFile(ptr, filename); + } + + public void translation(float tx, float ty, float tz) + { + this.setTranslation(ptr, tx, ty, tz); + } + + public void scale(float sx, float sy, float sz) + { + this.setScale(ptr, sx, sy, sz); + } + + public void rotate(float rx, float ry, float rz) { + this.setRotate(ptr, rx, ry, rz); + } + public void showGeom(boolean show) + { + this.setShow(ptr, "geom", show); + } + public void showMesh(boolean show) + { + this.setShow(ptr, "mesh", show); + } + public long getOnelab() { + return this.onelab; + } + public void ShowPopup(String message) { + handler.obtainMessage(0, message).sendToTarget(); + } + public void RequestRender() { + handler.obtainMessage(1).sendToTarget(); + } + public void SetLoading(String message) { + handler.obtainMessage(2, message).sendToTarget(); + } + public void SetLoading(int percent) { + handler.obtainMessage(3, percent, 100).sendToTarget(); + } +} diff --git a/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java b/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java new file mode 100644 index 0000000000..885845d0ee --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java @@ -0,0 +1,806 @@ +package org.geuz.onelab; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.opengl.GLSurfaceView; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.ProgressDialog; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.Configuration; +import android.content.res.XmlResourceParser; +import android.graphics.Color; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.SubMenu; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.ScrollView; +import android.widget.Spinner; +import android.widget.TableLayout; +import android.widget.TableRow; +import android.widget.TextView; + +public class MainActivity extends Activity { + + private mGLSurfaceView glView; + private GLESRender renderer; + private ProgressDialog loading; + private AlertDialog.Builder dialogBuilder; + private Models modelList; + private int model; + private Gmsh gmsh; + private Button run, reset; + private UndragableViewPager pager; + private List<Parameter> params = new ArrayList<Parameter>(); + private SeparatedListView paramListView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + //this.requestWindowFeature(Window.FEATURE_NO_TITLE); + + LinearLayout layout = new LinearLayout(this); + loading = new ProgressDialog(this); + layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + layout.setOrientation(LinearLayout.VERTICAL); + pager = new UndragableViewPager(this); + pager.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + pager.setAdapter(new AdaptedPager()); + pager.setOffscreenPageLimit(3); + pager.setCurrentItem(0); + layout.addView(pager); + dialogBuilder = new AlertDialog.Builder(this); + + gmsh = new Gmsh("", mainHandler); + modelList = new Models(); + getModels(); + loadNative(); + if(modelList.size() > 0){ + model = 0; + String tmp = getFilesDir()+ "/" + modelList.getFile(model); + gmsh.load(tmp); + } + setContentView(layout); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuItem listitem = menu.add(Menu.NONE, Menu.NONE, Menu.NONE, R.string.menu_list); + if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) + { + MenuItem paramitem = menu.add(Menu.NONE, Menu.NONE, Menu.NONE, R.string.menu_settings); + paramitem.setIcon(R.drawable.ic_settings); + paramitem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + } + MenuItem modelitem = menu.add(Menu.NONE, Menu.NONE, Menu.NONE, R.string.menu_model); + MenuItem postitem = menu.add(Menu.NONE, Menu.NONE, Menu.NONE, R.string.menu_postpro); + SubMenu viewitem = menu.addSubMenu(R.string.menu_view); + + + listitem.setIcon(R.drawable.ic_list); + modelitem.setIcon(R.drawable.ic_mesh); + listitem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + modelitem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + postitem.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); + + viewitem.add(R.string.menu_view_x); + viewitem.add(R.string.menu_view_y); + viewitem.add(R.string.menu_view_z); + viewitem.add(R.string.menu_view_scale); + viewitem.add(R.string.menu_view_translation); + return true; + } + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + if(item.getTitle().equals(getString(R.string.menu_settings))) + pager.setCurrentItem(1, true); + else if(item.getTitle().equals(getString(R.string.menu_list))) + pager.setCurrentItem(0, true); + else if (item.getTitle().equals(getString(R.string.menu_model))) + pager.setCurrentItem(2, true); + else if(item.getTitle().equals(getString(R.string.menu_postpro))){ + dialogBuilder.setTitle("Post proccessing") + .setView(postproView()) + .setPositiveButton("Ok", null) + .show(); + } + else if(item.getTitle().equals(getString(R.string.menu_view_x))){ + renderer.rotate(0, 0, 0); + renderer.rotate(90, 0, 0); + glView.requestRender(); + } + else if(item.getTitle().equals(getString(R.string.menu_view_y))){ + renderer.rotate(0, 0, 0); + renderer.rotate(0, 90, 0); + glView.requestRender(); + } + else if(item.getTitle().equals(getString(R.string.menu_view_z))){ + renderer.rotate(0, 0, 0); + glView.requestRender(); + } + else if(item.getTitle().equals(getString(R.string.menu_view_scale))){ + glView.resetScale(); + glView.requestRender(); + } + else if(item.getTitle().equals(getString(R.string.menu_view_translation))){ + renderer.translate(0, 0, 0); + glView.requestRender(); + } + return super.onMenuItemSelected(featureId, item); + } + + private class UndragableViewPager extends ViewPager{ + + public UndragableViewPager(Context context) { + super(context); + } + @Override + public boolean onInterceptTouchEvent(MotionEvent arg0) { + return false; + //return super.onInterceptTouchEvent(arg0); + } + + } + + private class AdaptedPager extends PagerAdapter { + + @Override + public Object instantiateItem(ViewGroup container, int position) { + switch (position) { + case 0: // Select a model + View listView = listView(container.getContext()); + container.addView(listView); + listView.setPadding(15, 10, 10, 5); + listView.setBackgroundColor(Color.argb(255, 67, 67, 67)); + return listView; + case 1: // Parameters + (MainActivity.this).getAvailableParam(); + View paramView = (MainActivity.this).paramView(container.getContext()); + container.addView(paramView); + paramView.setPadding(15, 10, 10, 5); + return paramView; + case 2: // OpenGL ES view + renderer = new GLESRender(gmsh); + glView = new mGLSurfaceView(container.getContext(), renderer); + //TODO the glView seems break the ViewPager (black square appear ...) + glView.setEGLContextClientVersion(1); + glView.setRenderer(renderer); + glView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); + + container.addView(glView); + return glView; + default: // ??? + View defaultView = new View(container.getContext()); + defaultView.setBackgroundColor(Color.argb(255, 255, 0, 0)); + container.addView(defaultView); + return defaultView; + } + } + + @Override + public int getCount() { + return 3; + } + + @Override + public float getPageWidth(int position) { + getResources().getConfiguration(); + if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) + { + switch (position) { + case 1: + if((MainActivity.this).getWindowManager().getDefaultDisplay().getWidth() < 500 ) + return 1f; + return 0.25f; + case 2: + if((MainActivity.this).getWindowManager().getDefaultDisplay().getWidth() < 500 ) + return 1f; + return 0.75f; + default: + return 1f; + } + } + switch (position) { + case 1: + if((MainActivity.this).getWindowManager().getDefaultDisplay().getWidth() < 500 ) + return 1f; + return 0.5f; + case 2: + return 1f; + default: + return 1f; + } + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return(view == object); + } + + } + + private void getAvailableParam(){ + String[] tmp = gmsh.getParams(); + for(String s : tmp){ // for each parameters in onelab + boolean found = false; + for(Parameter p : params){ // for each parameters + if(s.split("\n")[2].equals(p.getName())){ // the parameter already exist, just refresh it + if(p.getType().equals("ParameterNumber")) + ((ParameterNumber)p).fromString(s); + else if(p.getType().equals("ParameterString")) + ((ParameterString)p).fromString(s); + found = true; + break; + } + } + if(found) continue; + // add new parameter + if(s.split("\n")[1].equals("number")){ + final ParameterNumber mParam = new ParameterNumber(this, gmsh, glView, ""); + if(mParam.fromString(s) == -1) continue; + params.add(mParam); + if(paramListView != null){ + paramListView.addItem(mParam.getName().split("/")[0].equals("Parameters")? mParam.getName().split("/")[0] + " > " + mParam.getName().split("/")[1]: mParam.getName().split("/")[0], mParam.getView()); + } + } + else if(s.split("\n")[1].equals("string")){ + ParameterString mParam = new ParameterString(this, gmsh, glView, ""); + if(mParam.fromString(s) != -1){ + params.add(mParam); + if(paramListView != null) + paramListView.addItem(mParam.getName().split("/")[0], mParam.getView()); + } + } + } + } + + private void getModels() + { + XmlResourceParser parser = getResources().getXml(R.xml.models); + int eventType; + try { + eventType = parser.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) { + if(eventType == XmlPullParser.START_DOCUMENT){ + eventType = parser.next(); + continue; + } + else if(eventType == XmlPullParser.START_TAG && parser.getName().equals("model")) { + String title = "", file = "", summary = ""; + while(eventType != XmlPullParser.END_TAG || !parser.getName().equals("model")) + { + + eventType = parser.next(); + if(eventType == XmlPullParser.START_TAG && parser.getName().equals("title")){ + eventType = parser.next(); + if(eventType == XmlPullParser.TEXT) + title = parser.getText(); + } + else if(eventType == XmlPullParser.START_TAG && parser.getName().equals("summary")){ + eventType = parser.next(); + if(eventType == XmlPullParser.TEXT) + summary = parser.getText(); + } + else if(eventType == XmlPullParser.START_TAG && parser.getName().equals("file")){ + eventType = parser.next(); + if(eventType == XmlPullParser.TEXT) + file = parser.getText(); + } + } + if(title.length() > 0) modelList.addModel(title, summary, file); + } + eventType = parser.next(); + } + } catch (XmlPullParserException e) { + // TODO Error in XML file + e.printStackTrace(); + } catch (IOException e) { + // TODO Error in XML file + e.printStackTrace(); + } + + } + + /** + * Load file from res/raw/ directory to the files directory of the application. + */ + private void loadNative() + { + for( Field f : R.raw.class.getFields()) { + try { + int Msh = f.getInt(null), i; + String androidName = getResources().getResourceEntryName(Msh); + StringBuilder tmp = new StringBuilder(androidName); + tmp.setCharAt(androidName.lastIndexOf('_'), '.'); + String nativeName = tmp.toString(); + String nativeExtension = nativeName.substring(nativeName.lastIndexOf('.')); + /*if(new File(getFilesDir().toString()+"/"+nativeName).exists()){ + //TODO check if the files are the same + continue; + }*/ + InputStream mshFile = getResources().openRawResource(Msh); + + FileOutputStream outputStream = openFileOutput(nativeName, Context.MODE_WORLD_READABLE); + byte[] buffer = new byte[2048]; + + while ((i = mshFile.read(buffer, 0, buffer.length)) > 0) + outputStream.write(buffer,0,i); + + } catch (IllegalArgumentException e) { + Log.e("Load files", "Error " + e.toString()); + + } catch (IllegalAccessException e) { + Log.e("Load files", "Error " + e.toString()); + + } catch (IOException e) { + Log.e("Load files", "Error " + e.toString()); + } + } + } + + private View postproView() { + ScrollView scroll = new ScrollView(this); + scroll.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + String[] PViews = gmsh.getPView(); + if(PViews.length < 1){ + LinearLayout layout = new LinearLayout(this); + TextView noPView = new TextView(this); + noPView.setText("There is no post processing data !"); + layout.addView(noPView); + return layout; + } + TableLayout table = new TableLayout(this); + table.setColumnShrinkable(0, true); + TableRow title = new TableRow(this); + TextView title_name = new TextView(this); + TextView title_intervalType = new TextView(this); + TextView title_intervals = new TextView(this); + title_name.setText("Name"); + title_intervals.setText("Intervals"); + title_intervalType.setText("Interval type"); + title.addView(title_name); + title.addView(title_intervalType); + title.addView(title_intervals); + table.addView(title); + for(int i=PViews.length-1; i >= 0;i--){ + TableRow row = new TableRow(this); + final int myID =i; + String[] infos = PViews[i].split("\n"); // name / IntervalsType (1=Iso 2=Continous 3=Discrete 4=Numeric) + CheckBox checkbox = new CheckBox(this); + final Spinner spinner = new Spinner(this); + final EditText nbIso = new EditText(this); + checkbox.setText(infos[0]); + checkbox.setChecked(infos[2].equals("1")); + checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + gmsh.setPView(myID, -1, (isChecked)? 1 : 0, -1); + spinner.setEnabled(isChecked); + glView.requestRender(); + } + }); + spinner.setEnabled(infos[2].equals("1")); + ArrayList<String> choices; + ArrayAdapter<String> adapter; + choices = new ArrayList<String>(); + choices.add("Iso-values"); + choices.add("Continous map"); + choices.add("Filled iso-values"); + adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, choices); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(adapter); + spinner.setSelection(Integer.parseInt(infos[1])-1); + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + + public void onItemSelected(AdapterView<?> parent, View view, + int pos, long id) { + gmsh.setPView(myID, pos+1, -1, -1); + glView.requestRender(); + nbIso.setEnabled(pos == 0 || pos == 2); + } + public void onNothingSelected(AdapterView<?> arg0) {} // Unused Auto-generated method stub + }); + nbIso.setText(infos[3]); + nbIso.setRawInputType(Configuration.KEYBOARD_12KEY); + nbIso.setOnKeyListener(new View.OnKeyListener() { + + public boolean onKey(View v, int keyCode, KeyEvent event) { + if(keyCode == KeyEvent.KEYCODE_ENTER){ // hide the keyboard + InputMethodManager imm = (InputMethodManager)getSystemService( + Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(nbIso.getWindowToken(), 0); + return true; + } + return false; + } + }); + nbIso.addTextChangedListener(new TextWatcher() { + + public void onTextChanged(CharSequence s, int start, int before, int count) { + + int nIso = 1; + try { + if(s.length() < 1) nIso = 1; + else nIso = Integer.parseInt(s.toString()); + } + catch(NumberFormatException e) + { + nIso = 1; + nbIso.setText(""); + } + if(nIso > 1000) {gmsh.setPView(myID, -1, -1, 1000); nbIso.setText("1000");} + else if(nIso > 0) gmsh.setPView(myID, -1, -1, nIso); + else gmsh.setPView(myID, -1, -1, 1); + glView.requestRender(); + } + + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} // UNUSED Auto-generated method stub + public void afterTextChanged(Editable s) {} // UNUSED Auto-generated method stub + + }); + row.addView(checkbox); + row.addView(spinner); + row.addView(nbIso); + table.addView(row); + } + scroll.addView(table); + return scroll; + } + + private View paramView(Context ctx) { + LinearLayout layout = new LinearLayout(this); + layout.setOrientation(LinearLayout.VERTICAL); + /*TextView title = new TextView(ctx); + title.setText(R.string.title_parameter); + title.setTextAppearance(ctx, android.R.style.TextAppearance_DeviceDefault_Large); + title.setTextColor(Color.BLACK);*/ + run = new Button(ctx); + reset = new Button(ctx); + run.setText("Run"); + reset.setText("Reset"); + //reset.setEnabled(false); + run.setOnClickListener(new OnClickListener() {public void onClick(View v) { + if(run.getText().equals("Show step")) + { + loading.show(); + return; + } + boolean changed = false; + for(Parameter p : params){ + if(p.changed()){ + changed = true; + break; + } + } + if(changed){ + new Run().execute(); + //gmsh.onelabCB("compute"); + + } + getAvailableParam(); + + pager.setCurrentItem(2, true); + }}); + reset.setOnClickListener(new OnClickListener() {public void onClick(View v) { + if(gmsh.onelabCB("reset") == 1){ + getAvailableParam(); + glView.requestRender(); + } + pager.setCurrentItem(1, true); + }}); + LinearLayout onelabBtns = new LinearLayout(this); + onelabBtns.setOrientation(LinearLayout.HORIZONTAL); + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + lp.weight = 1; + onelabBtns.addView(reset, lp); + onelabBtns.addView(run, lp); + CheckBox showMesh = new CheckBox(ctx); + showMesh.setText("Show the mesh"); + showMesh.setChecked(false); + showMesh.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + gmsh.showMesh(isChecked); + glView.requestRender(); + } + }); + CheckBox showGeom = new CheckBox(ctx); + showGeom.setText("Show the geometry"); + showGeom.setChecked(true); + showGeom.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + gmsh.showGeom(isChecked); + glView.requestRender(); + } + }); + paramListView = new SeparatedListView(ctx, new View[] {showMesh, showGeom, onelabBtns}); + paramListView.setDividerHeight(0); + for(Parameter p : params) + { + paramListView.addItem(p.getName().split("/")[0].equals("Parameters")? p.getName().split("/")[0] + " > " + p.getName().split("/")[1]: p.getName().split("/")[0], p.getView()); + p.setList(paramListView); + } + /*LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + layoutParams.weight = 1; + layout.addView(paramListView, layoutParams); + layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + layoutParams.weight = 0; + layoutParams.gravity = Gravity.BOTTOM; + layout.addView(onelabBtns,layoutParams); + return layout;*/ + //layout.addView(onelabBtns); + //layout.addView(paramListView); + //return layout; + return paramListView; + } + + private View listView(Context ctx) { + LinearLayout layout = new LinearLayout(ctx); + layout.setOrientation(LinearLayout.VERTICAL); + ListView list = new ListView(ctx); + list.setAdapter( new ModeleArrayAdapter(ctx, modelList)); + list.setOnItemClickListener(new OnItemClickListener() { + + public void onItemClick(AdapterView<?> parent, View view, int position, + long id) { + model = (position < modelList.size())? position : 0; + String tmp = getFilesDir() + "/" + modelList.getFile(model); + gmsh.load(tmp); + + params.clear(); + paramListView.clear(); + getAvailableParam(); + if(params.size()>0)params.get(params.size() - 1)._changed = true; // Hack for the first run + glView.requestRender(); + pager.setCurrentItem(1); + } + }); + layout.addView(list); + Button loadSD = new Button(ctx); + loadSD.setText(R.string.button_open_external_file); + loadSD.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT)); + loadSD.setOnClickListener(new OnClickListener() { + + public void onClick(View v) { + @SuppressWarnings("unused") + SDFileChooser f = new SDFileChooser(); + } + }); + layout.addView(loadSD); + return layout; + } + + private class SDFileChooser{ + File curentPath; + FileDialog dialog; + + public SDFileChooser() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { + curentPath = Environment.getExternalStorageDirectory(); + + showList(getFile(curentPath)); + } + else + showMessage(R.string.error_nosdcard); + } + + public void setPath(String newPath) { + curentPath = new File(newPath); + showList(getFile(curentPath)); + + } + public String getPath() { + return curentPath.toString(); + } + + private void showList(String[] list) { + if(!curentPath.toString().equals(Environment.getExternalStorageDirectory().toString())){ + String[] newList = new String[list.length + 1]; + for(int i=0;i<list.length;i++) + newList[i+1] = list[i]; + newList[0] = ".."; + list = newList; + } + if(list.length < 1){ + showMessage(R.string.error_nomshfile); + return; + } + if(dialog != null) dialog.dismiss(); + dialog = new FileDialog(this, list); + dialog.show(getFragmentManager(), "files"); + } + + private void showMessage(int msg) { + dialog = new FileDialog(this, msg); + dialog.show(getFragmentManager(), "msg"); + } + + private String[] getFile(File path) { + return path.list(new FilenameFilter() { + + public boolean accept(File dir, String filename) { + String ext = filename.substring(filename.lastIndexOf(".") + 1, filename.length()); + File curent = new File(dir.toString()+"/"+filename); + if(curent.isHidden()) + return false; + else if(curent.isDirectory()) + return true; + else if(ext.equals("MSH") || ext.equals("msh")) + return true; + else + return false; + } + }); + } + private class FileDialog extends DialogFragment { + + String[] list; + int msg = -1; + SDFileChooser parent; + + public FileDialog(SDFileChooser p, String[] l) { + list = l; + parent = p; + } + public FileDialog(SDFileChooser p, int m) { + msg = m; + parent = p; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + if(msg > 0) { + builder.setMessage(R.string.error_nomshfile) + .setPositiveButton(R.string.button_ok, null); + } + else { + builder.setTitle(R.string.dialog_title_choosefile); + builder.setItems(list, new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int which) { + if(list[which].equals("..")) + parent.setPath(curentPath.getParentFile().toString()); + else if( new File(parent.getPath() + "/" + list[which]).isDirectory()) + parent.setPath(parent.getPath() + "/" + list[which]); + else { + String ext = list[which].substring(list[which].lastIndexOf(".") + 1, list[which].length()); + if(ext.equals("MSH") || ext.equals("msh")) { + gmsh.load(curentPath+"/"+getFile(curentPath)[which]); + glView.requestRender(); + } + } + } + }); + } + return builder.create(); + }; + } + + } + + private class Run extends AsyncTask<Void, Void, Integer[]> { + + @Override + protected void onPreExecute() { + loading.setTitle("Please wait"); + loading.setButton(DialogInterface.BUTTON_NEUTRAL, "Hide", new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int which) { + loading.dismiss(); + } + }); + loading.setButton(DialogInterface.BUTTON_NEGATIVE, "Stop", new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int which) { + //loading.dismiss(); + //run.setText("Run"); + gmsh.onelabCB("stop"); + run.setEnabled(false); + //cancel(true); + } + }); + loading.setMessage("..."); + loading.show(); + //run.setEnabled(false); + run.setText("Show progress"); + super.onPreExecute(); + } + + @Override + protected Integer[] doInBackground(Void... params) { + gmsh.onelabCB("compute"); + return new Integer[] {1}; + } + + @Override + protected void onPostExecute(Integer[] result) { + loading.dismiss(); + //run.setEnabled(true); + run.setText("Run"); + run.setEnabled(true); + glView.requestRender(); + super.onPostExecute(result); + } + + } + + private final Handler mainHandler = new Handler(){ + public void handleMessage(android.os.Message msg) { + switch (msg.what) { + case 0: // we get a message from gmsh library + String message =(String) msg.obj; + dialogBuilder + .setTitle("Erreur Gmsh/GetDP") + .setMessage(message) + .setPositiveButton("Continue", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }) + .show(); + + break; + case 1: // request render from gmsh library + if(glView != null) + glView.requestRender(); + getAvailableParam(); + break; + case 2: // we get a message for loading + String loadingMessage =(String) msg.obj; + loading.setMessage(loadingMessage); + break; + case 3: // we get a progress for loading + loading.setProgress(msg.arg1); + break; + default: + break; + } + }; + }; +} diff --git a/contrib/mobile/Android/src/org/geuz/onelab/ModeleArrayAdapter.java b/contrib/mobile/Android/src/org/geuz/onelab/ModeleArrayAdapter.java new file mode 100644 index 0000000000..03b200a8d9 --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/ModeleArrayAdapter.java @@ -0,0 +1,54 @@ +package org.geuz.onelab; + +import android.content.Context; +import android.graphics.Color; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +public class ModeleArrayAdapter extends ArrayAdapter<String> { + private Context context; + private String[] titres; + private String[] descriptions; + + public ModeleArrayAdapter(Context context, String[] titres) { + super(context, R.layout.model, titres); + this.context = context; + this.titres = titres; + } + public ModeleArrayAdapter(Context context, String[] titres, String[] descriptions) { + this(context,titres); + this.descriptions = descriptions; + } + public ModeleArrayAdapter(Context context, Models models) { + super(context, R.layout.model, models.getNames()); + this.context = context; + titres = new String[models.size()]; + descriptions = new String[models.size()]; + for(int i=0;i < models.size();i++) { + titres[i] = models.getName(i); + descriptions[i] = models.getSummary(i); + } + + } + + @Override + public View getView(int position, View convertView, ViewGroup parent){ + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + View rowView = inflater.inflate(R.layout.model, parent, false); + TextView Titre = (TextView) rowView.findViewById(R.id.titre); + TextView Description = (TextView) rowView.findViewById(R.id.description); + ImageView Icone = (ImageView) rowView.findViewById(R.id.icone); + if(this.titres != null) Titre.setText(this.titres[position]); + if(this.descriptions != null) Description.setText(this.descriptions[position]); + if(Icone != null) Icone.setImageResource(R.drawable.ic_launcher); + Icone.setPadding(10, 10, 10, 10); + + return rowView; + } +} diff --git a/contrib/mobile/Android/src/org/geuz/onelab/Models.java b/contrib/mobile/Android/src/org/geuz/onelab/Models.java new file mode 100644 index 0000000000..e5ab6f962a --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/Models.java @@ -0,0 +1,40 @@ +package org.geuz.onelab; + +import java.util.ArrayList; +import java.util.List; + + +class Models { + private List<String> _name; + private List<String> _summary; + private List<String> _file; + + public Models(){ + _name = new ArrayList<String>(); + _summary = new ArrayList<String>(); + _file = new ArrayList<String>(); + } + + public int size() { + return _name.size(); + } + public String getName(int pos) { + return _name.get(pos); + } + public String[] getNames() { + String[] ret = new String[_name.size()]; + ret = _name.toArray(ret); + return ret; + } + public String getSummary(int pos) { + return _summary.get(pos); + } + public String getFile(int pos) { + return _file.get(pos); + } + public void addModel(String name, String summary, String file){ + _name.add(name); + _file.add(file); + _summary.add(summary); + } +} diff --git a/contrib/mobile/Android/src/org/geuz/onelab/Parameter.java b/contrib/mobile/Android/src/org/geuz/onelab/Parameter.java new file mode 100644 index 0000000000..4e0040f566 --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/Parameter.java @@ -0,0 +1,85 @@ +package org.geuz.onelab; + + +import android.content.Context; +import android.graphics.Color; +import android.widget.LinearLayout; +import android.widget.TextView; + + +public class Parameter { + protected Context _context; + protected Gmsh _gmsh; + protected SeparatedListView _listView; + protected mGLSurfaceView _glView; + protected String _name; + protected String _label; + protected boolean _readOnly; + protected boolean _changed; + protected TextView _title; + + public Parameter(Context context, Gmsh gmsh, mGLSurfaceView glView, String name){ + _context = context; + _gmsh = gmsh; + _glView = glView; + _readOnly = false; + _name = name; + _title = new TextView(context); + _title.setText(name); + _title.setTextAppearance(context, android.R.style.TextAppearance_DeviceDefault_Medium); + _title.setTextColor(Color.DKGRAY); + } + public Parameter(Context context, Gmsh gmsh, mGLSurfaceView glView, String name, boolean readOnly){ + this(context, gmsh, glView, name); + _readOnly = readOnly; + _changed = false; + } + + protected void update(){ + if(_label != null && !_label.equals("")) + _title.setText(_label); + else { + String tmp[] = _name.split("/"); + _title.setText(tmp[tmp.length-1]); + } + if(isReadOnly()) _title.setAlpha(0.423f); + } + + public void setName(String name) {_name = name;this.update();} + public void setReadOnly(boolean readOnly) {_readOnly = readOnly;this.update();} + public void setLabel(String label) {_label = label;this.update();} + public String getName() {return _name;} + public boolean isReadOnly() {return _readOnly;} + public String getLabel() {return _label;} + public int fromString(String s){ + String[] infos = s.split("\n"); + int pos=0; + pos++;// version + pos++;// type + setName(infos[pos++]);// name + setLabel(infos[pos++]);// label + pos++;// help + pos++;// never change + pos++;// changed + if(Integer.parseInt(infos[pos++]) != 1)return -1;// visible + this.setReadOnly((infos[pos++].equals("1")));// read only + int nAttributes = Integer.parseInt(infos[pos++]);// number of attributes + pos+=(nAttributes*2);// key+value + int nClients = Integer.parseInt(infos[pos++]);// number of client + pos+=nClients;// clients + this.update(); + return pos; + } + public boolean changed() { if(_changed){_changed=false; return true;}return _changed;} + public String getType(){return "Parameter";} + + public void setList(SeparatedListView list){ _listView = list;} + + public LinearLayout getView() { + LinearLayout paramLayout = new LinearLayout(_context); + paramLayout.setOrientation(LinearLayout.VERTICAL); + paramLayout.addView(_title); + return paramLayout; + } +} + diff --git a/contrib/mobile/Android/src/org/geuz/onelab/ParameterNumber.java b/contrib/mobile/Android/src/org/geuz/onelab/ParameterNumber.java new file mode 100644 index 0000000000..73f0ce1659 --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/ParameterNumber.java @@ -0,0 +1,270 @@ +package org.geuz.onelab; + +import java.util.ArrayList; + +import android.content.Context; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.SeekBar; +import android.widget.Spinner; + +public class ParameterNumber extends Parameter{ + private double _value, _min, _max, _step; + private SeekBar _bar; + private ArrayList<Double> _values; + private ArrayList<String> _choices; + private ArrayAdapter<String> _adapter; + private Spinner _spinner; + private CheckBox _checkbox; + private EditText _edittext; + + public ParameterNumber(Context context, Gmsh gmsh, mGLSurfaceView glView, String name){ + super(context, gmsh, glView, name); + } + public ParameterNumber(Context context, Gmsh gmsh, mGLSurfaceView glView, String name, double value, double min, double max, double step) + { + this(context, gmsh, glView, name); + _value = value; + _min = min; + _max = max; + _step = step; + } + public ParameterNumber(Context context, Gmsh gmsh, mGLSurfaceView glView, String name, boolean readOnly, double value, double min, double max, double step) + { + this(context, gmsh, glView, name, value, min, max, step); + _readOnly = readOnly; + } + + protected void update(){ + super.update(); + int nDecimal = String.valueOf(this.getStep()).length() - String.valueOf(this.getStep()).lastIndexOf('.') - 1; // hack for double round + if(_bar != null){ + if(_label != null && !_label.equals("")) + _title.setText(_label + " (" + Math.round(_value*Math.pow(10, nDecimal))/Math.pow(10, nDecimal) + ")"); + else { + String tmp[] = _name.split("/"); + _title.setText(tmp[tmp.length-1] + " (" + Math.round(_value*Math.pow(10, nDecimal))/Math.pow(10, nDecimal) + ")"); + } + _bar.setProgress((int) ((_value-_min)/_step)); + _bar.setMax((int) ((_max-_min)/_step)); + _bar.setEnabled(!this.isReadOnly()); + } + else if(_spinner != null) + { + for(int i=0;i<_choices.size();i++) + if(_values.get(i) == _value) + _spinner.setSelection(i, true); + } + else if(_checkbox != null) + { + if(_label != null) _checkbox.setText(_label); + else _checkbox.setText(_name); + _checkbox.setChecked((_value == 0)? false : true); + } + else if(_edittext != null) + { + _edittext.setText(""+Math.round(_value*Math.pow(10, nDecimal))/Math.pow(10, nDecimal)); + } + } + + public void setValue(double value) { + if(value < _min || value > _max) { + Log.w("ParameterNumber", "Incorect value "+value+" (max="+_max+" min="+_min+")"); + return; + } + if(value != _value) + _changed = true; + _value = value; + this.update(); + } + public void setMin(double min) {_min = min;this.update();} + public void setMax(double max) {_max = max;this.update();} + public void setStep(double step) {_step = step;this.update();} + public void addChoice(double choice, String value) { + if(_values == null) { + _values = new ArrayList<Double>(); + _choices = new ArrayList<String>(); + _values.add(choice); + _choices.add(value); + if(_spinner == null) { + _spinner = new Spinner(_context); + _adapter = new ArrayAdapter<String>(_context, android.R.layout.simple_spinner_dropdown_item, _choices); + _adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + _spinner.setAdapter(_adapter); + } + } + else + { + for(int i=0;i<_values.size();i++) { + if(_values.get(i).equals(choice) && _choices.size() > i) { + _choices.set(i, value); + return; + } + else if(_values.get(i).equals(choice)) + { + _choices.add(value); + return; + } + } + _values.add(choice); + _choices.add(value); + } + } + public double getValue() {return _value;} + public double getMax() {return _max;} + public double getMin() {return _min;} + public double getStep() {return _step;} + public int fromString(String s){ + int pos = super.fromString(s); + if(pos <= 0) return -1; // error + String[] infos = s.split("\n"); + String tmpVal = infos[pos++]; + if(tmpVal.equals("Inf")) // TODO set value to max ??? + _value = 1; + else + _value = Double.parseDouble(tmpVal); + this.setMin(Double.parseDouble(infos[pos++])); + this.setMax(Double.parseDouble(infos[pos++])); + this.setStep(Double.parseDouble(infos[pos++])); + pos++;// index + int nChoix = Integer.parseInt(infos[pos++]); // choices' size + double choices[] = new double[nChoix]; + for(int i=0; i<nChoix; i++) + if(nChoix == 2) + choices[i] = Double.parseDouble(infos[pos++]); // choice + else pos++; + int nLabels = Integer.parseInt(infos[pos++]); // labels' size + if(nChoix == 2 && choices[0] == 0 && choices[1] == 1 && nLabels == 0) { + _checkbox = new CheckBox(_context); + this.update(); + return pos; + } + for(int i=0; i<nLabels && nChoix == nLabels; i++) + { + double val = Double.parseDouble(infos[pos++]); // choice + this.addChoice(val, infos[pos++]); // label + } + // ... + if(nLabels < 1 && _step == 0) + _edittext = new EditText(_context); + else if(nLabels < 1) + _bar = new SeekBar(_context); + this.update(); + return pos; + } + public String getType(){return "ParameterNumber";} + public LinearLayout getView(){ + LinearLayout paramLayout = new LinearLayout(_context); + paramLayout.setOrientation(LinearLayout.VERTICAL); + paramLayout.addView(_title); + if(_spinner != null) { + paramLayout.addView(_spinner); + _spinner.setEnabled(!_readOnly); + _spinner.setOnFocusChangeListener(new View.OnFocusChangeListener() { + + public void onFocusChange(View v, boolean hasFocus) { + if(_listView != null) _listView.refresh(); + } + }); + _spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + + public void onNothingSelected(AdapterView<?> arg0) {} + + public void onItemSelected(AdapterView<?> parent, View view, + int pos, long id) { + if(_listView != null) _listView.refresh(); + setValue(_values.get(pos)); + _gmsh.setParam(getType(), getName(), String.valueOf(_values.get(pos))); + if(_gmsh.onelabCB("check") == 1 && _glView != null) + _glView.requestRender(); + } + + }); + } + else if(_bar != null) { + paramLayout.addView(_bar); + _bar.setEnabled(!_readOnly); + _bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + + public void onStopTrackingTouch(SeekBar seekBar) { + _gmsh.setParam(getType(), getName(), String.valueOf(getValue())); // update parameter and the perform a check + if(_gmsh.onelabCB("check") == 1 && _glView != null) + _glView.requestRender(); + } + + public void onStartTrackingTouch(SeekBar seekBar) {} + + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if(_listView != null) _listView.refresh(); + setValue(getMin() + getStep()*(double)progress); + } + }); + } + else if(_checkbox != null) { + paramLayout.removeView(_title); + paramLayout.addView(_checkbox); + _checkbox.setEnabled(!_readOnly); + _checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if(_listView != null) _listView.refresh(); + setValue((isChecked)? 1 : 0); + _gmsh.setParam(getType(), getName(), String.valueOf(_value)); + } + }); + } + else if(_edittext != null){ + paramLayout.addView(_edittext); + _edittext.setEnabled(!_readOnly); + + _edittext.setOnKeyListener(new View.OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + if(keyCode == KeyEvent.KEYCODE_ENTER){ // hide the keyboard + InputMethodManager imm = (InputMethodManager)_context.getSystemService( + Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(_edittext.getWindowToken(), 0); + _gmsh.setParam(getType(), getName(), String.valueOf(_value)); + _edittext.clearFocus(); + return true; + } + if(keyCode > KeyEvent.KEYCODE_9 && keyCode != KeyEvent.KEYCODE_NUMPAD_DOT && (keyCode <KeyEvent.KEYCODE_NUMPAD_0 || keyCode >KeyEvent.KEYCODE_NUMPAD_9) && keyCode != KeyEvent.KEYCODE_DEL) + return true; + return false; + } + }); + _edittext.addTextChangedListener(new TextWatcher() { + + public void onTextChanged(CharSequence s, int start, int before, int count) { + if(_listView != null) _listView.refresh(); + double value = 1; + try { + if(s.length() < 1) value = 1; + else value = Double.parseDouble(s.toString()); + } + catch(NumberFormatException e) + { + value = 1; + //_edittext.setText(""); + } + _value = value; + _changed = true; + } + + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} // UNUSED Auto-generated method stub + public void afterTextChanged(Editable s) {} // UNUSED Auto-generated method stub + + }); + } + return paramLayout; + } +} diff --git a/contrib/mobile/Android/src/org/geuz/onelab/ParameterString.java b/contrib/mobile/Android/src/org/geuz/onelab/ParameterString.java new file mode 100644 index 0000000000..d1048d0d2c --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/ParameterString.java @@ -0,0 +1,152 @@ +package org.geuz.onelab; + +import java.util.ArrayList; + +import android.content.Context; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.Spinner; + +public class ParameterString extends Parameter{ + + private String _kind; + private int _index; + private ArrayList<String> _choices; + private ArrayAdapter<String> _adapter; + private Spinner _spinner; + private EditText _edittext; + + public ParameterString(Context context, Gmsh gmsh, mGLSurfaceView glView, String name) { + super(context, gmsh, glView, name); + _choices = new ArrayList<String>(); + _choices.add("-"); // Default choice + } + + private void createSpinner() + { + if(_spinner != null) return; + _spinner = new Spinner(_context); + _adapter = new ArrayAdapter<String>(_context, android.R.layout.simple_spinner_dropdown_item, _choices); + _adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + _spinner.setAdapter(_adapter); + } + + protected void update(){ + super.update(); + if(_spinner != null) + _spinner.setSelection(_index); + else if(_edittext != null && _choices.size() > 0) + _edittext.setText(_choices.get(0)); + } + + public void setValue(int index) {if(index != _index)_changed = true;_index = index;this.update();} + public void setValue(String value) { + int index = _choices.indexOf(value); + if(index < 0) { // the value is not in the list, add it + this.addChoices(value); + index = _choices.indexOf(value); + } + if(index != _index)_changed = true; + _index = index;this.update(); + } + public void setKind(String kind) {_kind = kind;} + public void addChoices(String choice) { + if(_edittext == null && _spinner == null) createSpinner(); + for(String c : _choices) // do not add a duplicate value + if(c.equals(choice))return; + if(_choices.get(0).equals("-")) // remove the default choice with the first added choice + _choices.remove(0); + _choices.add(choice); + this.update(); + } + public String getValue() {if( _index < 0) return "";return _choices.get(_index);} + public String getKind() {return _kind;} + public int getIndex() {return _index;} + public ArrayList<String> getChoices() {return _choices;} + public int fromString(String s){ + int pos = super.fromString(s); + if(pos <= 0) return -1; // error + String[] infos = s.split("\n"); + String value = infos[pos++]; + setKind(infos[pos++]); // generic file + if(_kind.equals("file")) + return -1; + int nChoices = Integer.parseInt(infos[pos++]); + if(nChoices < 1 && _kind.equals("generic")) + _edittext = new EditText(_context); + for(int i=0;i<nChoices;i++) this.addChoices(infos[pos++]); + // ... + setValue(value); + this.update(); + return pos; + } + public String getType(){return "ParameterString";} + public LinearLayout getView() { + LinearLayout paramLayout = new LinearLayout(_context); + paramLayout.setOrientation(LinearLayout.VERTICAL); + paramLayout.addView(_title); + if(_spinner != null){ + paramLayout.addView(_spinner); + _spinner.setEnabled(!_readOnly); + _spinner.setOnFocusChangeListener(new View.OnFocusChangeListener() { + + public void onFocusChange(View v, boolean hasFocus) { + if(_listView != null) _listView.refresh(); + } + }); + _spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + + public void onNothingSelected(AdapterView<?> arg0) {} + + public void onItemSelected(AdapterView<?> parent, View view, + int pos, long id) { + if(_listView != null) _listView.refresh(); + setValue(pos); + _gmsh.setParam(getType(), getName(), String.valueOf(getValue())); + if(_gmsh.onelabCB("check") == 1 && _glView != null) + _glView.requestRender(); + } + + }); + } + else if(_edittext != null){ + paramLayout.addView(_edittext); + _edittext.setEnabled(!_readOnly); + _edittext.setOnKeyListener(new View.OnKeyListener() { + + public boolean onKey(View v, int keyCode, KeyEvent event) { + if(keyCode == KeyEvent.KEYCODE_ENTER){ // hide the keyboard + InputMethodManager imm = (InputMethodManager)_context.getSystemService( + Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(_edittext.getWindowToken(), 0); + _edittext.clearFocus(); + return true; + } + return false; + } + }); + _edittext.addTextChangedListener(new TextWatcher() { + + public void onTextChanged(CharSequence s, int start, int before, int count) { + if(_listView != null) _listView.refresh(); + } + + public void beforeTextChanged(CharSequence s, int start, int count, + int after) {} // UNUSED Auto-generated method stub + + public void afterTextChanged(Editable s) { + _gmsh.setParam(getType(), getName(), _choices.get(0)); + } + }); + } + return paramLayout; + } + +} diff --git a/contrib/mobile/Android/src/org/geuz/onelab/SeparatedListView.java b/contrib/mobile/Android/src/org/geuz/onelab/SeparatedListView.java new file mode 100644 index 0000000000..a88285ef46 --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/SeparatedListView.java @@ -0,0 +1,144 @@ +package org.geuz.onelab; + +import java.util.ArrayList; +import java.util.List; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ListView; +import android.widget.TextView; + + +public class SeparatedListView extends ListView{ + + private SeparatedListAdaptater adapter; + private Context _context; + + public SeparatedListView(Context context) { + super(context); + _context = context; + adapter = new SeparatedListAdaptater(); + this.setAdapter(adapter); + } + public SeparatedListView(Context context, View[] footer) { + super(context); + _context = context; + for(View v : footer) + this.addFooterView(v); + adapter = new SeparatedListAdaptater(); + this.setAdapter(adapter); + } + + public void addItem(String header, View item) { + TextView title = (TextView)((LayoutInflater) _context.getSystemService( Context.LAYOUT_INFLATER_SERVICE )).inflate(R.layout.list_header, null); + title.setText(header); + adapter.addItem(header, title, item); + adapter.notifyDataSetChanged(); + this.invalidateViews(); + } + + public void refresh() + { + adapter.notifyDataSetChanged(); + this.invalidateViews(); + } + + public void clear() + { + adapter.clear(); + adapter.notifyDataSetChanged(); + } + + private class Section{ + private String _name; + private List<View> _items; + public Section(String name){ + _name = name; + _items = new ArrayList<View>(); + } + public void addItem(View v){ + _items.add(v); + } + public String getName(){ + return _name; + } + public int getItemsCount(){ + return _items.size(); + } + public View getItem(int pos){ + return _items.get(pos); + } + } + + private class SeparatedListAdaptater extends BaseAdapter{ + + List<Section> sections; + List<View> titles; + + public SeparatedListAdaptater() { + sections = new ArrayList<SeparatedListView.Section>(); + titles = new ArrayList<View>(); + } + + public void addItem(String header, View title, View item) { + for(Section s : sections){ + if(s.getName().equals(header)){ + s.addItem(item); + return; + } + } + Section s = new Section(header); + s.addItem(item); + sections.add(s); + titles.add(title); + } + + //@Override + public int getCount() { + int count = 0; + for(Section s : sections) count += s.getItemsCount() + 1; + return count; + } + + //@Override + public Object getItem(int position) { + // UNUSED Auto-generated method stub + return null; + } + + //@Override + public long getItemId(int position) { + // UNUSED Auto-generated method stub + return 0; + } + + //@Override + public View getView(int position, View convertView, ViewGroup parent) { + int section = -1, + lastPosition = -1; + while(lastPosition<position){ + int itemsCount = sections.get(section+1).getItemsCount(); + if(lastPosition+1 == position)// this is a section + return titles.get(section+1); + else if(lastPosition+1+itemsCount >= position){ // the view is in this section + if(section<0) return sections.get(section+1).getItem(position-1); + return sections.get(section+1).getItem(position-lastPosition-2); + } + lastPosition+= 1 + itemsCount; + section++; + } + return null; + } + public void clear() + { + sections.clear(); + titles.clear(); + } + + } + +} + diff --git a/contrib/mobile/Android/src/org/geuz/onelab/mGLSurfaceView.java b/contrib/mobile/Android/src/org/geuz/onelab/mGLSurfaceView.java new file mode 100644 index 0000000000..d57d57dfc6 --- /dev/null +++ b/contrib/mobile/Android/src/org/geuz/onelab/mGLSurfaceView.java @@ -0,0 +1,133 @@ +package org.geuz.onelab; + +import android.content.Context; +import android.opengl.GLSurfaceView; +import android.support.v4.view.MotionEventCompat; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.View; +import android.view.GestureDetector.OnDoubleTapListener; +import android.view.GestureDetector.OnGestureListener; +import android.view.ScaleGestureDetector.OnScaleGestureListener; + +class mGLSurfaceView extends GLSurfaceView { + private float scaleFactor = 1f; + private GestureDetector gesture; + private ScaleGestureDetector scaleGesture; + private float lastX, lastY; + private GLESRender _renderer; + public mGLSurfaceView(Context context, GLESRender renderer) { + super(context); + _renderer = renderer; + gesture = new GestureDetector(context, new GestureListener(this)); + scaleGesture = new ScaleGestureDetector(context, new OnScaleGestureListener() { + + public void onScaleEnd(ScaleGestureDetector detector) {}// UNUSED Auto-generated method stub + + public boolean onScaleBegin(ScaleGestureDetector detector) {return true;}// UNUSED Auto-generated method stub + + public boolean onScale(ScaleGestureDetector detector) { + scaleFactor *= detector.getScaleFactor(); + scaleFactor = Math.max(0.1f, Math.min(scaleFactor, 50.0f)); + _renderer.scale(scaleFactor, scaleFactor, scaleFactor); + requestRender(); + return true; + + } + }); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if(event.getPointerCount() >= 3){ + scaleGesture.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0,0, 0)); + + final float x = MotionEventCompat.getX(event, 1); + final float y = MotionEventCompat.getY(event, 1); + + int action = MotionEventCompat.getActionMasked(event); + + if(action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_1_DOWN){ + lastX = x; + lastY = y; + } + else if(action == MotionEvent.ACTION_MOVE){ + float dx = x - lastX, + dy = y - lastY; + if(dx != 0 || dy != 0) + _renderer.rotate(dy, dx, 0); + requestRender(); + lastX = x; + lastY = y; + } + + return true; + } + else { + scaleGesture.onTouchEvent(event); + return gesture.onTouchEvent(event); + } + + } + + private class GestureListener implements OnGestureListener, OnDoubleTapListener{ + //private View view; + public GestureListener(View view) { + //this.view = view; + } + public boolean onDown(MotionEvent e) { + // UNUSED Auto-generated method stub + return true; + } + + public boolean onFling(MotionEvent e1, MotionEvent e2, + float velocityX, float velocityY) { + // UNUSED Auto-generated method stub + return false; + } + + public void onLongPress(MotionEvent e) { + // UNUSED Auto-generated method stub + + } + + public boolean onScroll(MotionEvent e1, MotionEvent e2, + float distanceX, float distanceY) { + _renderer.translate(-distanceX, distanceY, 0f); + requestRender(); + return false; + } + + public void onShowPress(MotionEvent e) { + // UNUSED Auto-generated method stub + + } + + public boolean onSingleTapUp(MotionEvent e) { + // UNUSED Auto-generated method stub + return false; + } + public boolean onDoubleTap(MotionEvent e) { + // UNUSED Auto-generated method stub + return false; + } + public boolean onDoubleTapEvent(MotionEvent e) { + _renderer.translate(0f, 0f, 0f); + scaleFactor = 1f; + _renderer.scale(scaleFactor, scaleFactor, scaleFactor); + _renderer.rotate(0, 0, 0); + requestRender(); + return false; + } + public boolean onSingleTapConfirmed(MotionEvent e) { + // UNUSED Auto-generated method stub + return false; + } + + } + public void resetScale(){ + scaleFactor = 1f; + _renderer.scale(scaleFactor, scaleFactor, scaleFactor); + } +} -- GitLab