diff --git a/contrib/mobile/Android/AndroidManifest.xml b/contrib/mobile/Android/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..ce2626134e71902aed35b489a5bac80c64886a80 --- /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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-hdpi/ic_action_search.png differ 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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-hdpi/ic_launcher.png differ 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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-hdpi/ic_list.png differ 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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-hdpi/ic_mesh.png differ 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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-hdpi/ic_settings.png differ 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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-ldpi/ic_launcher.png differ 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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-mdpi/ic_action_search.png differ 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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-mdpi/ic_launcher.png differ 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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-mdpi/model.png differ 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 Binary files /dev/null and b/contrib/mobile/Android/res/drawable-mdpi/param.png differ 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 0000000000000000000000000000000000000000..bf26b6dcbd24c603ed3e04b11e93c677a95fca52 --- /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 0000000000000000000000000000000000000000..9301369f0178c43e413944495baed603ae270caa --- /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 0000000000000000000000000000000000000000..1458d87c831c5d7b0452af70388efdf3b3929714 --- /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 0000000000000000000000000000000000000000..f58a22b84a3d4258d4cb3e7100e5444ee87dc8e8 --- /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 0000000000000000000000000000000000000000..3e0a76ce5234d4b1e4e68260a702de10db21ee4c --- /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 0000000000000000000000000000000000000000..c0c7815711709f5b24c1a07a0057a045bb8df0c6 --- /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 0000000000000000000000000000000000000000..a18c7cdf4f64bfd69453b51477cbb2e8721eccff --- /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 0000000000000000000000000000000000000000..4c9c07d5c55c12586069e061c1d6fe867fecb106 --- /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 0000000000000000000000000000000000000000..37e1ac3756b8d223e7fda6adf651dfafc861216d --- /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 0000000000000000000000000000000000000000..c2760986cf88f4c497dd8c8c9257314770d99072 --- /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 0000000000000000000000000000000000000000..efade112ec7041f40cae86e572324f99da649652 --- /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 0000000000000000000000000000000000000000..225b29dd4fb482e800a1000ae94132e261b3d1e9 --- /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 0000000000000000000000000000000000000000..b9ee5ce16ab353f10ca3891a9ccb123b345922bc --- /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 0000000000000000000000000000000000000000..c051cf1a6da52b733f73e0548acccf70858e1fd4 --- /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 0000000000000000000000000000000000000000..e928a4a055c5b8f9809365103aabcbf2046b4f96 --- /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 0000000000000000000000000000000000000000..d60f76efbbb2752e474780b386bfd5adb7660f25 --- /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 0000000000000000000000000000000000000000..d408cbc37ad420e5564150e1989cb39f73539d35 --- /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 0000000000000000000000000000000000000000..1c089a788c5a75c13949344137ed3698f6d2341e --- /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 0000000000000000000000000000000000000000..eaf9831ea87c91d064cbf24e75fece511a2a3b13 --- /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 0000000000000000000000000000000000000000..4dba0d0a4c512d8ba1304ee0100e35aa9d78490a --- /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 0000000000000000000000000000000000000000..80b25aa292b832a095e3c84fe5642701a5ab489b --- /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 0000000000000000000000000000000000000000..2cb182e27f76a2c62cd437cbf49a912af730db39 --- /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 0000000000000000000000000000000000000000..f13d71f968f7f75bff5f72c2711cdba21813b023 --- /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 0000000000000000000000000000000000000000..885845d0eea08ffe3b5f637e8b3069aaa5404a86 --- /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 0000000000000000000000000000000000000000..03b200a8d91f91aa71b3119e10da2af5178c43b4 --- /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 0000000000000000000000000000000000000000..e5ab6f962a9884e9595fe057775a0c036f1f68c2 --- /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 0000000000000000000000000000000000000000..4e0040f566a13fdde0b2df72907c57f033c5e33d --- /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 0000000000000000000000000000000000000000..73f0ce165940502b134093c81427183d9beab619 --- /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 0000000000000000000000000000000000000000..d1048d0d2cce065b1a86354f2479524510313d42 --- /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 0000000000000000000000000000000000000000..a88285ef465ea752709c7ec5aa1ca0b6e3daee2d --- /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 0000000000000000000000000000000000000000..d57d57dfc68c6649d35f11e827101f6bf218d39d --- /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); + } +}