├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .gitlab-ci.yml ├── CONTRIBUTING.md ├── Data ├── .gitkeep ├── BakerLake.fig ├── BakerLakeScale.fig ├── SolarPowerGeneration.csv ├── WA_Lake Shannon_241902_1952_62500.jpg ├── car.mat ├── drawing.mat ├── explicitPDESoln.mp4 ├── hand2.mat ├── lakeData.mat ├── longLakeData.mat ├── modernLakeData.mat └── myStorm.mat ├── FunctionLibrary ├── CollectData.m ├── IdentifyLakeShape.m ├── LoadStormData.mlx ├── MeasureGeoScale.m ├── cnPDE.m ├── eulerMethod.m ├── eulerMethodDE.m ├── explicitPDE.m ├── gauss2pt.m ├── implicitPDE.m ├── linInterp.m ├── pcHInterp.m ├── pcSpline.m ├── rk4.m └── simpsonsRule.m ├── Images ├── AddOnsIcon.png ├── BakerLakeSR.png ├── Bird.png ├── EndIcon.png ├── EulerInt.png ├── NoisyDerivative.png ├── OpenInFX.png ├── OpenInMO.png ├── StormTrack.png ├── TestedWith.json ├── add-ons.png ├── eulerMethodDECheck.png ├── hand.png ├── heatSoln.gif ├── heatSoln.mp4 ├── image_11.png ├── image_6.png ├── image_8.png └── pendulum.png ├── InstructorResources └── Solutions │ ├── FunctionLibrarySolutions │ ├── cnPDESoln.m │ ├── cnPDEu0Soln.m │ ├── eulerBackwardDifferenceSoln.m │ ├── eulerMethodDESoln.m │ ├── eulerMethodSoln.m │ ├── explicitPDESoln.m │ ├── gauss2ptSoln.m │ ├── implicitPDESoln.m │ ├── improvedEulerSoln.m │ ├── linInterpSimpSoln.m │ ├── linInterpSoln.m │ ├── pcHInterpSoln.m │ ├── pcSplineSoln.m │ ├── rk4Soln.m │ └── simpsonsRuleSoln.m │ ├── HandSoln.mlx │ ├── ImplementExplicitSolverSoln.mlx │ ├── InterpolationSoln.mlx │ ├── MeasureLakeAreaSoln.mlx │ ├── NumericalDerivativesSoln.mlx │ ├── NumericalIntegrationSoln.mlx │ ├── NumericalODEsSoln.mlx │ ├── NumericalPDEsSoln.mlx │ ├── PendulumModelsSoln.mlx │ ├── TrackStormsSoln.mlx │ ├── myLakeData.mat │ └── myModernLakeData.mat ├── LICENSE.md ├── MainMenu.mlx ├── NumericalMethods.prj ├── README.md ├── README.mlx ├── SECURITY.md ├── Scripts ├── Hand.mlx ├── ImplementExplicitSolver.mlx ├── Interpolation.mlx ├── MeasureLakeArea.mlx ├── NumericalDerivatives.mlx ├── NumericalIntegration.mlx ├── NumericalODEs.mlx ├── NumericalPDEs.mlx ├── PendulumModels.mlx └── TrackStorms.mlx ├── SoftwareTests ├── CheckTestResults.m ├── FunctionTests.m ├── PostFiles │ ├── PostHand.m │ ├── PostHandSoln.m │ ├── PostImplementExplicitSolver.m │ ├── PostImplementExplicitSolverSoln.m │ ├── PostInterpolation.m │ ├── PostInterpolationSoln.m │ ├── PostMeasureLakeArea.m │ ├── PostMeasureLakeAreaSoln.m │ ├── PostNumericalDerivatives.m │ ├── PostNumericalDerivativesSoln.m │ ├── PostNumericalIntegration.m │ ├── PostNumericalIntegrationSoln.m │ ├── PostNumericalODEs.m │ ├── PostNumericalODEsSoln.m │ ├── PostNumericalPDEs.m │ ├── PostNumericalPDEsSoln.m │ ├── PostPendulumModels.m │ ├── PostPendulumModelsSoln.m │ ├── PostTrackStorms.m │ └── PostTrackStormsSoln.m ├── PostSmokeTest.m ├── PreFiles │ ├── PreHand.m │ ├── PreHandSoln.m │ ├── PreImplementExplicitSolver.m │ ├── PreImplementExplicitSolverSoln.m │ ├── PreInterpolation.m │ ├── PreInterpolationSoln.m │ ├── PreMeasureLakeArea.m │ ├── PreMeasureLakeAreaSoln.m │ ├── PreNumericalDerivatives.m │ ├── PreNumericalDerivativesSoln.m │ ├── PreNumericalIntegration.m │ ├── PreNumericalIntegrationSoln.m │ ├── PreNumericalODEs.m │ ├── PreNumericalODEsSoln.m │ ├── PreNumericalPDEs.m │ ├── PreNumericalPDEsSoln.m │ ├── PrePendulumModels.m │ ├── PrePendulumModelsSoln.m │ ├── PreTrackStorms.m │ └── PreTrackStormsSoln.m ├── RunAllTests.m ├── SmokeTests.m ├── SolnSmokeTests.m ├── TestResults_R2024a.txt ├── TestResults_R2024b.txt └── myLakeData.mat ├── Utilities ├── ProjectShutdown.m └── ProjectStartupApp.m └── resources └── project ├── 6xhH2l9GP9loT6TdFn_Mo65sDHg ├── P8PSrqcBHMbGhqD2r1d9oc0h3TUd.xml └── P8PSrqcBHMbGhqD2r1d9oc0h3TUp.xml ├── 8h3kimKoV3g5SPdcFPq6bNqde20 ├── 2R0-o249XdrxUDxChRL1MrtyIeEd.xml ├── 2R0-o249XdrxUDxChRL1MrtyIeEp.xml ├── ApixlSTDAdp3GgxzMHKu0Fhfr6Id.xml ├── ApixlSTDAdp3GgxzMHKu0Fhfr6Ip.xml ├── P0dCXqU2TY1GykJweoJ37itMc78d.xml ├── P0dCXqU2TY1GykJweoJ37itMc78p.xml ├── Qg7ozviHBAR9M3EKyM28wXK7XCQd.xml ├── Qg7ozviHBAR9M3EKyM28wXK7XCQp.xml ├── S2_lG2GXW82QbxegJJWd7IrKtlwd.xml ├── S2_lG2GXW82QbxegJJWd7IrKtlwp.xml ├── Xjlo1m2A3FCGrq601wagkpx_ycsd.xml ├── Xjlo1m2A3FCGrq601wagkpx_ycsp.xml ├── YH64LtKYtQhOo-dosLLP8CBfX3kd.xml ├── YH64LtKYtQhOo-dosLLP8CBfX3kp.xml ├── cG8QwElnYEQuaCWyUvA9YF124v8d.xml ├── cG8QwElnYEQuaCWyUvA9YF124v8p.xml ├── tDhuEtF2_L7Vzt3RGzNsc_A3TRYd.xml ├── tDhuEtF2_L7Vzt3RGzNsc_A3TRYp.xml ├── wCdpXJngLvCgG-kPbX2z7g_ijRYd.xml ├── wCdpXJngLvCgG-kPbX2z7g_ijRYp.xml ├── yvc00et_D9w1RZcV5T2-bniDUu0d.xml └── yvc00et_D9w1RZcV5T2-bniDUu0p.xml ├── BT5hWoz-UTefONdqForZyI91O8Y ├── 4JuqxfFjWu6twt8CqM4nt7feqakd.xml ├── 4JuqxfFjWu6twt8CqM4nt7feqakp.xml ├── 7-1B9IYtiDSgVt8bX4miP7Ae2qkd.xml ├── 7-1B9IYtiDSgVt8bX4miP7Ae2qkp.xml ├── Dc59WDtag_rG4XkTmXZI8D-rEHQd.xml ├── Dc59WDtag_rG4XkTmXZI8D-rEHQp.xml ├── P1l14w_H1m1DxTKzPmPMl1YHOhEd.xml ├── P1l14w_H1m1DxTKzPmPMl1YHOhEp.xml ├── Ur1esh7xN9L6aqDUKBE31DKE1Qod.xml ├── Ur1esh7xN9L6aqDUKBE31DKE1Qop.xml ├── Y4Dbs1ki764_FbTDx4JqKWeLH2cd.xml ├── Y4Dbs1ki764_FbTDx4JqKWeLH2cp.xml ├── cun28KIqfMV5dplLoh1WqjdCS8cd.xml ├── cun28KIqfMV5dplLoh1WqjdCS8cp.xml ├── nzB5D5dN-y0P0MZ52QkerA1i0Q4d.xml ├── nzB5D5dN-y0P0MZ52QkerA1i0Q4p.xml ├── vWXe0RyZPdhHUw9cHcgocR1TaiAd.xml ├── vWXe0RyZPdhHUw9cHcgocR1TaiAp.xml ├── wqJGEIaUV60vBsQBPjBwhhEPdzod.xml ├── wqJGEIaUV60vBsQBPjBwhhEPdzop.xml ├── xJol_hmopCm1uPehMxgeZG8rtcsd.xml └── xJol_hmopCm1uPehMxgeZG8rtcsp.xml ├── BjxNC43HIPP8KZwg_cceb68ikkA ├── dxW0rLxFMXm0cpQGCSkWQRi2YRsd.xml └── dxW0rLxFMXm0cpQGCSkWQRi2YRsp.xml ├── EEtUlUb-dLAdf0KpMVivaUlztwA ├── -upqjogKesBp3DwJRlG6KjrKvd4d.xml ├── -upqjogKesBp3DwJRlG6KjrKvd4p.xml ├── 2vfmNT5dFMoKB5FDZBSr3ouDAL8d.xml ├── 2vfmNT5dFMoKB5FDZBSr3ouDAL8p.xml ├── DxJWFQ6s-5tgLo-3uCpCdq16n-sd.xml ├── DxJWFQ6s-5tgLo-3uCpCdq16n-sp.xml ├── cn2Ee7NifKI7ffnw_Fjz5lrC1Qgd.xml ├── cn2Ee7NifKI7ffnw_Fjz5lrC1Qgp.xml ├── dNSwd3FTbBY0j-vjD3y6Lzhg5WQd.xml ├── dNSwd3FTbBY0j-vjD3y6Lzhg5WQp.xml ├── e1K2asjf1AG8_lJdlO0WXpNP2YQd.xml ├── e1K2asjf1AG8_lJdlO0WXpNP2YQp.xml ├── e7wCov_BYJUY6VsFZYx5ab3064gd.xml ├── e7wCov_BYJUY6VsFZYx5ab3064gp.xml ├── jSqfwSDlRVqL_9fEXfOnybDRVxod.xml ├── jSqfwSDlRVqL_9fEXfOnybDRVxop.xml ├── x9kRh-n1S7s6yE1EzN4stHJjWq0d.xml └── x9kRh-n1S7s6yE1EzN4stHJjWq0p.xml ├── HoHDHQ_WvHAAKj5aJOrvrg_vpt8 ├── xXlmKuOQ7YT_G1elNhbKQIUqSRMd.xml └── xXlmKuOQ7YT_G1elNhbKQIUqSRMp.xml ├── KAXfQgCar2Yb8zOxgvf9hdmLP1E ├── xcK8fO1pjra5DR0jot5vrzlBV84d.xml ├── xcK8fO1pjra5DR0jot5vrzlBV84p.xml ├── y8P_Fq2qJ6We-JIH8JyFmcTdT2wd.xml └── y8P_Fq2qJ6We-JIH8JyFmcTdT2wp.xml ├── NjSPEMsIuLUyIpr2u1Js5bVPsOs ├── 2kj09UetkV_lru3gvSPXnY6-nM4d.xml ├── 2kj09UetkV_lru3gvSPXnY6-nM4p.xml ├── KKyDJtbdIBOlaeHmIZd5VX6vqx8d.xml ├── KKyDJtbdIBOlaeHmIZd5VX6vqx8p.xml ├── QWNDYJD5mGW1bWYvPx9DtKnxzw4d.xml ├── QWNDYJD5mGW1bWYvPx9DtKnxzw4p.xml ├── R1RggVhA72agIvELiuhWPRS8F0Id.xml ├── R1RggVhA72agIvELiuhWPRS8F0Ip.xml ├── aEHSZBIY-yve10yGis12Zr5DLZod.xml ├── aEHSZBIY-yve10yGis12Zr5DLZop.xml ├── j4xwF_j8iFTVayUMfxLgMnTbencd.xml ├── j4xwF_j8iFTVayUMfxLgMnTbencp.xml ├── r8LR4nLmg9ai3oHrW1r_-KocQzkd.xml └── r8LR4nLmg9ai3oHrW1r_-KocQzkp.xml ├── Project.xml ├── ZN2RlSIbyWXhOxbxxI4hOawbMD4 ├── d1u4eIKNgMuS21WRxXrD0UScuR8d.xml ├── d1u4eIKNgMuS21WRxXrD0UScuR8p.xml ├── gjXMbSOzqQJbg7H7bMF0OVGji80d.xml ├── gjXMbSOzqQJbg7H7bMF0OVGji80p.xml ├── p5HYYVUpTuYgZwnT8QkkzaoJraUd.xml ├── p5HYYVUpTuYgZwnT8QkkzaoJraUp.xml ├── q4FWbcu8zEbneDjWzNwfvfvjQNAd.xml ├── q4FWbcu8zEbneDjWzNwfvfvjQNAp.xml ├── s-04wUzHjOhlMa1CW_zpJwm8iDMd.xml └── s-04wUzHjOhlMa1CW_zpJwm8iDMp.xml ├── fjRQtWiSIy7hIlj-Kmk87M7s21k ├── NjSPEMsIuLUyIpr2u1Js5bVPsOsd.xml └── NjSPEMsIuLUyIpr2u1Js5bVPsOsp.xml ├── iMwdHOXOBiBXhnA_li8gtEJVTjc ├── RMvf4mEDuznAOqU6SKNmIWErfxgd.xml ├── RMvf4mEDuznAOqU6SKNmIWErfxgp.xml ├── ZTr3GAe6p03ZVs2FdKKE0JsiFMQd.xml ├── ZTr3GAe6p03ZVs2FdKKE0JsiFMQp.xml ├── uIbyU9dPEHKvxjdwx5pD9PDDCZYd.xml └── uIbyU9dPEHKvxjdwx5pD9PDDCZYp.xml ├── qaw0eS1zuuY1ar9TdPn1GMfrjbQ ├── 8h3kimKoV3g5SPdcFPq6bNqde20d.xml ├── 8h3kimKoV3g5SPdcFPq6bNqde20p.xml ├── BT5hWoz-UTefONdqForZyI91O8Yd.xml ├── BT5hWoz-UTefONdqForZyI91O8Yp.xml ├── BjxNC43HIPP8KZwg_cceb68ikkAd.xml ├── BjxNC43HIPP8KZwg_cceb68ikkAp.xml ├── KocSmEw1PpelhlG7ZNeMUdHVtywd.xml ├── KocSmEw1PpelhlG7ZNeMUdHVtywp.xml ├── QMJD9OLFzxcTTbPOoh-ahQ4zTRUd.xml ├── QMJD9OLFzxcTTbPOoh-ahQ4zTRUp.xml ├── R0IsxKENiOKovWZXASFjrmpbBCYd.xml ├── R0IsxKENiOKovWZXASFjrmpbBCYp.xml ├── ZN2RlSIbyWXhOxbxxI4hOawbMD4d.xml ├── ZN2RlSIbyWXhOxbxxI4hOawbMD4p.xml ├── iMwdHOXOBiBXhnA_li8gtEJVTjcd.xml ├── iMwdHOXOBiBXhnA_li8gtEJVTjcp.xml ├── rh0jHbNfmojECiiHH7BQHmZTsWkd.xml ├── rh0jHbNfmojECiiHH7BQHmZTsWkp.xml ├── rnpMu7jn2QWt_rQcz8FJ-MxGzVId.xml └── rnpMu7jn2QWt_rQcz8FJ-MxGzVIp.xml ├── root ├── 6x1BhZX_fLnKpcwqra0qFwv1jIgp.xml ├── 6xhH2l9GP9loT6TdFn_Mo65sDHgp.xml ├── EEtUlUb-dLAdf0KpMVivaUlztwAp.xml ├── GiiBklLgTxteCEmomM8RCvWT0nQd.xml ├── GiiBklLgTxteCEmomM8RCvWT0nQp.xml ├── HoHDHQ_WvHAAKj5aJOrvrg_vpt8p.xml ├── KAXfQgCar2Yb8zOxgvf9hdmLP1Ep.xml ├── NmGqIpAwUJcXFyLjFAGnU9uyN5Yp.xml ├── WZRuNzqc-Db7NcQAZO8Y-R8U9ccp.xml ├── fjRQtWiSIy7hIlj-Kmk87M7s21kp.xml └── qaw0eS1zuuY1ar9TdPn1GMfrjbQp.xml ├── rootp.xml ├── uuid-366ca619-578a-4bc0-8012-bfa62d28c37f.xml └── uuid-768d5a75-b789-410a-bd37-37618930aace.xml /.gitattributes: -------------------------------------------------------------------------------- 1 | *.fig binary 2 | *.mat binary 3 | *.mdl binary diff merge=mlAutoMerge 4 | *.mdlp binary 5 | *.mexa64 binary 6 | *.mexw64 binary 7 | *.mexmaci64 binary 8 | *.mlapp binary linguist-language=MATLAB 9 | *.mldatx binary 10 | *.mlproj binary 11 | *.mlx binary merge=mlAutoMerge linguist-language=MATLAB 12 | *.p binary 13 | *.sfx binary 14 | *.sldd binary 15 | *.slreqx binary merge=mlAutoMerge 16 | *.slmx binary merge=mlAutoMerge 17 | *.sltx binary 18 | *.slxc binary 19 | *.slx binary merge=mlAutoMerge linguist-language=Simulink 20 | *.slxp binary 21 | 22 | ## Other common binary file types 23 | *.docx binary 24 | *.exe binary 25 | *.jpg binary 26 | *.pdf binary 27 | *.png binary 28 | *.xlsx binary 29 | 30 | # Ignore HTML 31 | 32 | *.html linguist-detectable=false 33 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: MATLAB Build 2 | 3 | # Controls when the action will run. 4 | on: 5 | push: 6 | branches: [ release ] 7 | pull_request: 8 | branches: [ release ] 9 | workflow_dispatch: 10 | 11 | # Add permission to write GitHub pages 12 | permissions: 13 | contents: write 14 | pages: write 15 | id-token: write 16 | 17 | jobs: 18 | test: 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | MATLABVersion: [R2024a,R2024b] 23 | runs-on: ubuntu-latest 24 | steps: 25 | # Checks-out your repository 26 | - uses: actions/checkout@v4 27 | 28 | # Sets up a display server 29 | - name: Start display server 30 | if: ${{ always() }} 31 | run: | 32 | sudo apt-get install xvfb 33 | Xvfb :99 & 34 | echo "DISPLAY=:99" >> $GITHUB_ENV 35 | 36 | # Sets up MATLAB 37 | - name: Setup MATLAB 38 | uses: matlab-actions/setup-matlab@v2 39 | with: 40 | release: ${{ matrix.MATLABVersion }} 41 | products: > 42 | Symbolic_Math_Toolbox 43 | Image_Processing_Toolbox 44 | Statistics_and_Machine_Learning_Toolbox 45 | Curve_Fitting_Toolbox 46 | Automated_Driving_Toolbox 47 | 48 | 49 | # Run all the tests 50 | - name: Run SmokeTests 51 | uses: matlab-actions/run-command@v2 52 | with: 53 | command: openProject(pwd); RunAllTests; 54 | 55 | # Upload the test results as artifact 56 | - name: Upload TestResults 57 | if: ${{ always() }} 58 | uses: actions/upload-artifact@v4 59 | with: 60 | name: TestResults_${{ matrix.MATLABVersion }} 61 | path: ./public/* 62 | overwrite: true 63 | 64 | badge: 65 | if: ${{ always() }} 66 | needs: [test] 67 | strategy: 68 | fail-fast: false 69 | runs-on: ubuntu-latest 70 | steps: 71 | 72 | # Checks-out your repository 73 | - uses: actions/checkout@v4 74 | 75 | # Sets up R2023b 76 | - name: Setup MATLAB 77 | uses: matlab-actions/setup-matlab@v2 78 | with: 79 | release: R2024b 80 | 81 | # Download the test results from artifact 82 | - name: Download All TestResults 83 | uses: actions/download-artifact@v4 84 | with: 85 | path: public 86 | pattern: TestResults_* 87 | merge-multiple: true 88 | 89 | # Create the test results badge 90 | - name: Run PostSmokeTest 91 | uses: matlab-actions/run-command@v2 92 | with: 93 | command: openProject(pwd); PostSmokeTest; 94 | 95 | # Deploy reports to GitHub pages 96 | - name: Setup Pages 97 | uses: actions/configure-pages@v5 98 | - name: Upload pages artifact 99 | uses: actions/upload-pages-artifact@v3 100 | with: 101 | path: public 102 | - name: Deploy to GitHub Pages 103 | id: deployment 104 | uses: actions/deploy-pages@v4 105 | 106 | # Commit the JSON for the MATLAB releases badge 107 | - name: Commit changed files 108 | continue-on-error: true 109 | run: | 110 | git config user.name "${{ github.workflow }} by ${{ github.actor }}" 111 | git config user.email "<>" 112 | git pull 113 | git add Images/TestedWith.json 114 | git commit Images/TestedWith.json -m "Update CI badges ${{ github.ref_name }}" 115 | git fetch 116 | git push 117 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # List of untracked files to ignore 2 | 3 | # Autosave files 4 | */*.asv 5 | *.asv 6 | *.m~ 7 | *.autosave 8 | *.slx.r* 9 | *.mdl.r* 10 | 11 | # MATLAB Drive 12 | *.MATLABDriveTag 13 | 14 | # Compiled files 15 | *.mex* 16 | *.p 17 | 18 | # Compressed files 19 | *.zip 20 | 21 | # Packaged app and toolbox files 22 | *.mlappinstall 23 | *.mltbx 24 | 25 | # Deployable archives 26 | *.ctf 27 | 28 | # Generated helpsearch folders 29 | helpsearch*/ 30 | 31 | # Defined Simulink cache folder 32 | Utilities/SimulinkCache/* 33 | 34 | # Standard code generation folders 35 | slprj/ 36 | sccprj/ 37 | codegen/ 38 | 39 | # Code generation file 40 | *.eep 41 | *.elf 42 | *.hex 43 | *.bin 44 | 45 | # Cache files 46 | *.slxc 47 | 48 | # Project settings and other local data 49 | Utilities/ProjectSettings.mat 50 | Data/allStorms.mat 51 | Data/allStorms.csv 52 | Scripts/myLakeData.mat 53 | myLakeData.mat 54 | 55 | # GitLab page folder 56 | public/ -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | # Set up two testing paths 3 | - setup 4 | - test 5 | - deploy 6 | - release 7 | 8 | setup-job: 9 | tags: 10 | - matlab 11 | stage: setup 12 | script: 13 | - cd .. 14 | - if (test-path utilities) { rm -r -force utilities } 15 | - git clone git@insidelabs-git.mathworks.com:modular-curriculum-content/utilities.git 16 | - cd $CI_PROJECT_NAME 17 | allow_failure: false 18 | 19 | 20 | smoke-test: 21 | # Smoke tests should run all the time 22 | tags: 23 | # Add additional tags like (e.g. - arduino) as required 24 | # Make sure that the runner you plan to use matches the tags 25 | - matlab 26 | stage: test 27 | parallel: 28 | matrix: 29 | - VERSION: [R2024a,R2024b] 30 | script: 31 | - Set-Alias -Name matlab -Value "C:\Program Files\MATLAB\$VERSION\bin\matlab.exe" 32 | - matlab -batch "openProject(pwd);RunAllTests" 33 | when: always 34 | allow_failure: true 35 | artifacts: 36 | name: "$VERSION" 37 | paths: 38 | - public/* 39 | when: always 40 | 41 | 42 | pages: 43 | tags: 44 | - matlab 45 | stage: deploy 46 | script: 47 | - matlab -batch "openProject(pwd);PostSmokeTest;" 48 | artifacts: 49 | paths: 50 | - public 51 | 52 | file-test: 53 | tags: 54 | - matlab 55 | stage: release 56 | script: 57 | - matlab -batch "proj = openProject(pwd); 58 | addpath(proj.RootFolder+'/InternalFiles/Tests/CI'); 59 | results = runtests('OpenCloseFileTest.m'); 60 | disp(table(results)); assertSuccess(results);" 61 | rules: 62 | # This test should always run when merging to main 63 | # And be available for manual running on any push 64 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH 65 | when: always 66 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH 67 | when: manual 68 | allow_failure: true 69 | 70 | release-testing: 71 | tags: 72 | - matlab 73 | stage: release 74 | script: 75 | - matlab -batch "proj = openProject(pwd); 76 | cd ..; 77 | addpath(genpath(fullfile('utilities','TestingResources'))); 78 | addpath(genpath(fullfile('utilities','Tools'))); 79 | runCMTests" 80 | rules: 81 | # This test should always run when merging to main 82 | # And be available for manual running on any push 83 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH 84 | when: always 85 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH 86 | when: manual 87 | allow_failure: true 88 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | >_If you believe you have discovered a security vulnerability, please **do not** open an issue or make a pull request. Follow the instructions in the [SECURITY.md](SECURITY.md) file in this repository._ 4 | 5 | Thank you for your interest in contributing to a MathWorks repository! We encourage contributions large and small to this repository. 6 | 7 | **Contributions do not have to be code!** If you see a way to explain things more clearly or a great example of how to use something, please contribute it (or a link to your content). We welcome issues even if you don't code the solution. We also welcome pull requests to resolve issues that we haven't gotten to yet! 8 | 9 | ## How to give feedback 10 | * **Send us an email:** Contact the [MathWorks teaching resources team.](mailto:onlineteaching@mathworks.com) 11 | * **Open an issue:** Start by [creating an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-an-issue) in the repository that you're interested in. That will start a conversation with the maintainer. When you are creating a bug report, please include as many details as possible. Please remember that other people do not have your background or understanding of the issue; make sure you are clear and complete in your description. 12 | 13 | ## How to contribute to the repository 14 | * **Work in your own public fork:** If you choose to make a contribution, you should [fork the repository](https://docs.github.com/en/get-started/quickstart/fork-a-repo). This creates an editable copy on GitHub where you can write, test, and refine your changes. We suggest that you keep your changes small and focused on the issue you submitted. 15 | * **Sign a Contributor License Agreement (CLA):** We require that all outside contributors sign a [CLA](https://en.wikipedia.org/wiki/Contributor_License_Agreement) before we can accept your contribution. When you create a pull request (see below), we'll reach out to you if you do not already have one on file. Essentially, the CLA gives us permission to publish your contribution as part of the repository. 16 | * **Make a pull request:** "[Pull Request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests)" is a confusing term, but it means exactly what it says: You're requesting that the maintainers of the repository pull your changes in. If you don't have a CLA on file, we'll reach out to you. Your contribution will be reviewed, and we may ask you to revise your pull request based on our feedback. Once everyone is satisfied, we'll merge your pull request into the repository. 17 | 18 | ## Guidelines 19 | 20 | We don't have best practices for writing MATLAB® code, but we do have some recommendations: 21 | 22 | * You should not have any warnings or errors in the [code analyzer report](http://www.mathworks.com/help/matlab/matlab_prog/matlab-code-analyzer-report.html) 23 | * [Loren Shure's blog](https://blogs.mathworks.com/loren) has [great advice on improving your MATLAB code](https://blogs.mathworks.com/loren/category/best-practice/) 24 | * Examples should be written as [live scripts](https://www.mathworks.com/help/matlab/matlab_prog/what-is-a-live-script-or-function.html) or [Simulink® models](https://www.mathworks.com/help/simulink/index.html). 25 | * We adhere to the [CommonMark](https://commonmark.org/) specification where it does not conflict with GitHub rendering. If you edit your Markdown in Visual Studio Code or a similar editor, it uses [markdownlint](https://github.com/DavidAnson/markdownlint) to highlight issues in your Markdown. 26 | 27 | **Again, thanks for contributing, and we look forward to your issues and pull requests!** 28 | -------------------------------------------------------------------------------- /Data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/.gitkeep -------------------------------------------------------------------------------- /Data/BakerLake.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/BakerLake.fig -------------------------------------------------------------------------------- /Data/BakerLakeScale.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/BakerLakeScale.fig -------------------------------------------------------------------------------- /Data/WA_Lake Shannon_241902_1952_62500.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/WA_Lake Shannon_241902_1952_62500.jpg -------------------------------------------------------------------------------- /Data/car.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/car.mat -------------------------------------------------------------------------------- /Data/drawing.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/drawing.mat -------------------------------------------------------------------------------- /Data/explicitPDESoln.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/explicitPDESoln.mp4 -------------------------------------------------------------------------------- /Data/hand2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/hand2.mat -------------------------------------------------------------------------------- /Data/lakeData.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/lakeData.mat -------------------------------------------------------------------------------- /Data/longLakeData.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/longLakeData.mat -------------------------------------------------------------------------------- /Data/modernLakeData.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/modernLakeData.mat -------------------------------------------------------------------------------- /Data/myStorm.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Data/myStorm.mat -------------------------------------------------------------------------------- /FunctionLibrary/CollectData.m: -------------------------------------------------------------------------------- 1 | function [x,y] = CollectData() 2 | % figure('position',get(0,'screensize')) 3 | % figure("WindowState","maximized") 4 | figure 5 | axes('position',[0 0 1 1]) 6 | grid on 7 | grid minor 8 | str = ["Select control points around your image by clicking and then double-click ", ... 9 | "to finish data collection. Close the figure window to return to the script."]; 10 | annotation("textbox",[.05 .9 .1 .1],"String",str,"FitBoxToText","on") 11 | ax = gca; 12 | roi = drawpolygon(ax); 13 | x = roi.Position(:,1); 14 | y = roi.Position(:,2); 15 | end 16 | -------------------------------------------------------------------------------- /FunctionLibrary/IdentifyLakeShape.m: -------------------------------------------------------------------------------- 1 | function roi = IdentifyLakeShape 2 | fig = uifigure("Name","Trace the outline of the lake"); 3 | gx = geoaxes("Parent",fig); 4 | geoplot(gx,48.7,-121.658) 5 | geolimits(gx,[48.63,48.75],[-121.665 -121.65]) 6 | geobasemap(gx,'satellite') 7 | roi = drawpolygon(gx); 8 | end -------------------------------------------------------------------------------- /FunctionLibrary/LoadStormData.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/FunctionLibrary/LoadStormData.mlx -------------------------------------------------------------------------------- /FunctionLibrary/MeasureGeoScale.m: -------------------------------------------------------------------------------- 1 | function longScale = MeasureGeoScale 2 | fig = uifigure("Name","Measure 2 km"); 3 | gx = geoaxes("Parent",fig); 4 | geoplot(gx,48.7,-121.658) 5 | geolimits(gx,[48.63,48.75],[-121.665 -121.65]) 6 | geobasemap(gx,'satellite') 7 | roi = drawpolygon(gx); 8 | longVals = roi.Position(:,2); 9 | 10 | longScale = 2/(longVals(2)-longVals(1)); 11 | 12 | end -------------------------------------------------------------------------------- /FunctionLibrary/cnPDE.m: -------------------------------------------------------------------------------- 1 | function u = cnPDE(f,alpha,beta,tEnd,dx,gamma,L) 2 | % Solve the 1D heat equation u_t = gamma*u_{xx} on a rod of length L 3 | % using the Crank-Nicolson method 4 | % u(t,0) = alpha(t) 5 | % u(t,L) = beta(t) 6 | % u(0,x) = f(x) 7 | % The desired spatial resolution is dx 8 | % Output is u = u(tEnd,x_m), a vector of values on the mesh points 9 | 10 | % %% Define dt with reference to both error and stability concerns 11 | % Optimal step size dtOpt for stability 12 | dtOpt = nan; 13 | 14 | % Forcing an integer numbers of dt steps that terminate at tEnd 15 | dt = tEnd/ceil(tEnd/dtOpt); 16 | 17 | % %% Set up helper values for defining the required matrices A and B 18 | % %% such as the number of rows, the value of mu, etc 19 | 20 | 21 | % %% Define modA for the explicit updating rule 22 | % %% modA-I = (A-I)/2, where I is the identity matrix 23 | 24 | 25 | % %% Define modB for the implicit updating rule 26 | % %% modB-I = (B-I)/2, where I is the identity matrix 27 | 28 | 29 | % %% Initialize bAvg = b^(j)+b^(j+1) as a vector of zeros 30 | 31 | 32 | % %% Define a spatial mesh vector xVals 33 | xVals = [0;0;0]; 34 | 35 | % %% Set up a column vector u0 of the initial values of u when t=0 36 | u0 = 0; 37 | u = u0; 38 | 39 | % %% Initialize the output to the interior points of u0 40 | 41 | 42 | % To visualize the outputs 43 | p = plot(xVals,u0,"LineWidth",4); 44 | ax = p.Parent; 45 | 46 | % Set the y limits to reasonable fixed values 47 | minAlpha = min(alpha(0:dt:tEnd)); 48 | maxAlpha = max(alpha(0:dt:tEnd)); 49 | minBeta = min(beta(0:dt:tEnd)); 50 | maxBeta = max(beta(0:dt:tEnd)); 51 | yLower = min([ax.YLim(1),minAlpha,minBeta]); 52 | yUpper = max([ax.YLim(2),maxAlpha,maxBeta]); 53 | scale = (yUpper-yLower)*0.05; 54 | ax.YLim = [yLower-scale yUpper+scale]; 55 | 56 | % These values generate well-sized y limits for the example function 57 | % used in partialDiffEqs.mlx 58 | ylim([-4 1.5]); 59 | title("Solving $\frac{\partial u}{\partial t} = \gamma \frac{\partial^2 u}{\partial x^2}$","Interpreter","latex") 60 | subtitle("$t=0$","Interpreter","latex") 61 | xlabel("$x$","Interpreter","latex") 62 | ylabel("$u$","Interpreter","latex") 63 | 64 | % %% Compute new values for halfB*u^(j+1)-b^(j+1) = halfA*u^(j)+b^(j) 65 | % %% Loop over timesteps to reach tEnd 66 | for j = 1:(tEnd/dt) 67 | 68 | 69 | % To visualize the outputs 70 | hold on 71 | delete(ax.Children(1:end-1)); 72 | plot(xVals,[alpha(j*dt);u;beta(j*dt)],LineWidth=1,SeriesIndex="none") 73 | subtitle("$t = $"+dt*j) 74 | drawnow 75 | pause(0.1) 76 | hold off 77 | % End visualization code 78 | end 79 | 80 | end 81 | -------------------------------------------------------------------------------- /FunctionLibrary/eulerMethod.m: -------------------------------------------------------------------------------- 1 | function [xApprox,yApprox]=eulerMethod(f,init,n,h) 2 | arguments 3 | f function_handle % integrand, e.g. @(x) x.^2 4 | init (1,2) double % initial value (x0,y0) 5 | n (1,1) double {mustBePositive,mustBeInteger} % number of steps 6 | h (1,1) double % step size 7 | end 8 | 9 | % The function returns two length (n+1) vectors of 10 | % estimated x and y values 11 | 12 | % Initialize the output with the initial value 13 | % Initialize the output with the initial value 14 | xApprox = nan(n+1,1); 15 | yApprox = nan(n+1,1); 16 | xApprox(1) = init(1); 17 | yApprox(1) = init(2); 18 | 19 | % Fill in the details of the implementation here 20 | 21 | end -------------------------------------------------------------------------------- /FunctionLibrary/eulerMethodDE.m: -------------------------------------------------------------------------------- 1 | function [xApprox,yApprox]=eulerMethodDE(f,init,n,h) 2 | arguments 3 | f function_handle % derivative dy/dt = f(t,y) 4 | init (1,2) double % initial value [t0 y0] 5 | n (1,1) double {mustBePositive,mustBeInteger} % number of steps 6 | h (1,1) double % step size 7 | end 8 | % f is a function handle, e.g. @(t,y) t.^2.*cos(y) 9 | 10 | % The function returns two length (n+1) vectors of 11 | % estimated x and y values 12 | 13 | % Initialize the output with the initial value 14 | % Initialize the output with the initial value 15 | xApprox = nan(n+1,1); 16 | yApprox = nan(n+1,1); 17 | xApprox(1) = init(1); 18 | yApprox(1) = init(2); 19 | 20 | % Fill in the details of the implementation here 21 | 22 | 23 | end -------------------------------------------------------------------------------- /FunctionLibrary/explicitPDE.m: -------------------------------------------------------------------------------- 1 | function u = explicitPDE(f,alpha,beta,tEnd,dx,gamma,L) 2 | % Solve the 1D heat equation u_t = gamma*u_{xx} on a rod of length L 3 | % u(t,0) = alpha(t) 4 | % u(t,L) = beta(t) 5 | % u(0,x) = f(x) 6 | % The desired spatial resolution is dx 7 | % Output is u = u(tEnd,x_m), a vector of values on the mesh points 8 | 9 | 10 | % Define dt with reference to both error and stability concerns 11 | % Optimal dt for stability 12 | dtOpt = dx^2/(2*gamma); 13 | % Forcing an integer numbers of dt steps that terminate at tEnd 14 | dt = tEnd/ceil(tEnd/dtOpt); 15 | 16 | % % testing %%%%%%%%%% 17 | % dt = 0.005; 18 | 19 | % Define helper values 20 | numRows = L/dx-1; 21 | mu = gamma*dt/(dx^2); 22 | baseDiag = ones(1,numRows); 23 | 24 | % % Define A for the updating rule 25 | % % u^(j+1) = A*u^(j)+b^(j) 26 | A = eye(numRows); 27 | 28 | % Initialize b as a vector of zeros 29 | b = zeros(numRows,1); 30 | 31 | % Define a spatial mesh vector 32 | xVals = linspace(0,L,round(L/dx)+1); 33 | 34 | % Set up a column vector u0 of the initial values of u when t=0 35 | u0 = (f(xVals))'; 36 | 37 | % Initialize the output to the interior points of u0 38 | u = u0(2:end-1); 39 | 40 | % To visualize the outputs 41 | p = plot(xVals,u0,"LineWidth",4); 42 | ax = p.Parent; 43 | 44 | % Set the y limits to reasonable fixed values 45 | minAlpha = min(alpha(0:dt:tEnd)); 46 | maxAlpha = max(alpha(0:dt:tEnd)); 47 | minBeta = min(beta(0:dt:tEnd)); 48 | maxBeta = max(beta(0:dt:tEnd)); 49 | yLower = min([ax.YLim(1),minAlpha,minBeta]); 50 | yUpper = max([ax.YLim(2),maxAlpha,maxBeta]); 51 | scale = (yUpper-yLower)*0.05; 52 | ax.YLim = [yLower-scale yUpper+scale]; 53 | 54 | title("Solving $\frac{\partial u}{\partial t} = \gamma \frac{\partial^2 u}{\partial x^2}$","Interpreter","latex") 55 | subtitle("$t=0$","Interpreter","latex") 56 | xlabel("$x$","Interpreter","latex") 57 | ylabel("$u$","Interpreter","latex") 58 | 59 | % Compute new values for u^(j+1) = Au^(j)+b^(j) 60 | % Loop over timesteps to reach tEnd 61 | for j = 0:(tEnd/dt - 1) 62 | % % Fill in the values for b in this iteration 63 | 64 | % % Compute the updated value of u 65 | 66 | % To visualize the outputs 67 | hold on 68 | delete(ax.Children(1:end-1)); 69 | plot(xVals,[alpha((j+1)*dt);u;beta((j+1)*dt)],"LineWidth",4,SeriesIndex="none") 70 | subtitle("$t = $"+dt*(j+1)) 71 | drawnow 72 | pause(0.1) 73 | hold off 74 | % End visualization code 75 | end 76 | 77 | end -------------------------------------------------------------------------------- /FunctionLibrary/gauss2pt.m: -------------------------------------------------------------------------------- 1 | function Fapprox = gauss2pt(f,a,b) 2 | % gauss2pt takes three arguments 3 | % f is a function handle 4 | % a and b are the bounds of a definite integral 5 | % 6 | % Fapprox returns the Gaussian 2 point approximation of the 7 | % integral from a to b of f(x) dx 8 | 9 | % Fill in the details of the implementation here so your 10 | % code will return a correct approximation of the area 11 | Fapprox = f((b+a)/2); 12 | end -------------------------------------------------------------------------------- /FunctionLibrary/implicitPDE.m: -------------------------------------------------------------------------------- 1 | function u = implicitPDE(f,alpha,beta,tEnd,dx,gamma,L) 2 | % Solve the 1D heat equation u_t = gamma*u_{xx} on a rod of length L 3 | % u(t,0) = alpha(t) 4 | % u(t,L) = beta(t) 5 | % u(0,x) = f(x) 6 | % The desired spatial resolution is dx 7 | % Output is u = u(tEnd,x_m), a vector of values on the mesh points 8 | 9 | 10 | % Define dt with reference to both error and stability concerns 11 | % Optimal dt for stability 12 | dtOpt = dx^2; 13 | % Forcing an integer numbers of dt steps that terminate at tEnd 14 | dt = tEnd/ceil(tEnd/dtOpt); 15 | 16 | % Set up the helper values for defining the required matrices 17 | numRows = L/dx-1; 18 | mu = gamma*dt/(dx^2); 19 | baseDiag = ones(1,numRows); 20 | 21 | % % Define B for the updating rule 22 | % % Bu^(j+1)-b^(j+1) = u^(j) 23 | B = eye(numRows); 24 | 25 | % Initialize b as a vector of zeros 26 | b = zeros(numRows,1); 27 | 28 | % Define a spatial mesh vector 29 | xVals = linspace(0,L,round(L/dx)+1); 30 | 31 | % Set up a column vector u0 of the initial values of u when t=0 32 | u0 = (f(xVals))'; 33 | 34 | % Initialize the output to the interior points of u0 35 | u = u0(2:end-1); 36 | 37 | % To visualize the outputs 38 | p = plot(xVals,u0,"LineWidth",4); 39 | ax = p.Parent; 40 | 41 | % Set the y limits to reasonable fixed values 42 | minAlpha = min(alpha(0:dt:tEnd)); 43 | maxAlpha = max(alpha(0:dt:tEnd)); 44 | minBeta = min(beta(0:dt:tEnd)); 45 | maxBeta = max(beta(0:dt:tEnd)); 46 | yLower = min([ax.YLim(1),minAlpha,minBeta]); 47 | yUpper = max([ax.YLim(2),maxAlpha,maxBeta]); 48 | scale = (yUpper-yLower)*0.05; 49 | ax.YLim = [yLower-scale yUpper+scale]; 50 | 51 | title("Solving $\frac{\partial u}{\partial t} = \gamma \frac{\partial^2 u}{\partial x^2}$","Interpreter","latex") 52 | subtitle("$t=0$","Interpreter","latex") 53 | xlabel("$x$","Interpreter","latex") 54 | ylabel("$u$","Interpreter","latex") 55 | 56 | % Compute new values for B*u^(j+1) - b^(j+1) = Au^(j) 57 | % Loop over timesteps to reach tEnd 58 | for j = 0:(tEnd/dt - 1) 59 | % % Update the values of b for this iteration 60 | 61 | % % Solve for the new value of u 62 | 63 | % To visualize the outputs 64 | hold on 65 | delete(ax.Children(1:end-1)); 66 | plot(xVals,[alpha((j+1)*dt);u;beta((j+1)*dt)],"SeriesIndex",1,"LineWidth",4) 67 | subtitle("$t = $"+dt*(j+1)) 68 | drawnow 69 | pause(0.1) 70 | hold off 71 | % End visualization code 72 | end 73 | 74 | end -------------------------------------------------------------------------------- /FunctionLibrary/linInterp.m: -------------------------------------------------------------------------------- 1 | function yNew = linInterpSoln(xData,yData,xNew) 2 | % linInterp interpolates the points (xNew(i),yNew(i)) using a 3 | % piecewise linear interpolation on the input data xData and 4 | % output data yData 5 | 6 | 7 | % Initialize output values vector 8 | yNew = nan(size(xNew)); 9 | 10 | % Determine if xData is increasing or decreasing 11 | % 12 | % Decide if you are going to redefine xData and yData to be only 13 | % increasing (or only decreasing) or if you are going to handle 14 | % each case separately 15 | 16 | % Check each value in xNew and determine its 17 | % corresponding interpolated value in yNew 18 | 19 | 20 | end -------------------------------------------------------------------------------- /FunctionLibrary/pcHInterp.m: -------------------------------------------------------------------------------- 1 | function yNew = pcHInterp(xData,yData,xNew) 2 | % xData is assumed to be a uniformly increasing vector and all values 3 | % xNew should be contained in the interval [xData(1),xData(end)] 4 | % Use the piecewise cubic spline formulas defined in interpolation.m 5 | % to compute interpolated values yNew at points xNew 6 | 7 | % %% Ensure that xData and yData are column vectors 8 | [xRows,~] = size(xData); 9 | [yRows,~] = size(yData); 10 | if xRows == 1 11 | xData = xData'; 12 | end 13 | if yRows == 1 14 | yData = yData'; 15 | end 16 | 17 | % %% Set up the value of n = number of points in xData 18 | 19 | 20 | 21 | % %% Calculate the vector of values h tracking the step sizes between 22 | % points in xData 23 | 24 | 25 | % %% Calculate the vector of slopes m tracking the slopes between 26 | % (xData(i),yData(i)) and (xData(i+1),yData(i+1)) 27 | % Remember to use pointwise operations 28 | 29 | 30 | % %% Determine the values of the slopes for the interpolant 31 | d = nan(n,1); 32 | % %% Start by calculating the slopes at interior points d(2:n-1) 33 | % If the sign of the slope changes between xData(i-1) and xData(i+1), or 34 | % if the slope is 0 in interval i-1 or i, set d(i) to be 0. 35 | % Otherwise, use a weighted centered difference approximation 36 | % where (w1+w2)/d(i) = w1/m(i-1)+w2/m(i) 37 | % with w1 = 2*h(i)+h(i-1) and w2 = 2*h(i-1)+h(i) 38 | 39 | 40 | 41 | % Add the slopes at i=1 and i=n using the formula 42 | d(1) = ((2*h(1)+h(2))*m(1)-h(1)*m(2))/(h(1)+h(2)); 43 | d(n) = ((2*h(n-1)+h(n-2))*m(n-1)-h(n-1)*m(n-2))/(h(n-1)+h(n-2)); 44 | 45 | % Check if the computed value will give an overshoot value 46 | d(1) = checkOvershoot(d(1),m(1),m(2)); 47 | d(n) = checkOvershoot(d(n),m(n-1),m(n-2)); 48 | 49 | % %% Set up the coefficients for P(x) in each interval where 50 | % xData(k) <= x < xData(k+1) and P_k(x) = a3*s^3+a2*s^2+a1*s+a0 51 | a3 = -2*m+d(1:end-1)+d(2:end); 52 | a2 = 3*m-2*d(1:end-1)-d(2:end); 53 | a1 = d(1:end-1); 54 | a0 = yData(1:end-1); 55 | 56 | % %% Initialize the output vector yNew 57 | yNew = nan(size(xNew)); 58 | 59 | % %% Loop over all entries in xNew and compute the interpolated value 60 | for i = 1:length(xNew) 61 | % For each value xNew(i), determine the value k such that 62 | % xData(k) <= xNew(i) < xData(k+1) 63 | j = 1; 64 | while xData(j) <= xNew(i) && j < length(xData) 65 | k=j; 66 | j = j+1; 67 | end 68 | if xNew(i)==xData(end) 69 | yNew(i) = yData(end); 70 | else 71 | % Evaluate the local variables s = xNew(i)-x_k 72 | s = xNew(i)-xData(k); 73 | % Use the polynomial formula P_k(x) to evaluate yNew = P_k(xNew(i)) 74 | yNew(i) = a3(k)*s^3+a2(k)*s^2+a1(k)*s+a0(k); 75 | end 76 | end 77 | end 78 | function d = checkOvershoot(d,m1,m2) 79 | if sign(d) ~= sign(m1) 80 | d=0; 81 | elseif sign(d) ~= sign(m2) & (abs(d)>abs(3*m1)) 82 | d = 3*m1; 83 | end 84 | end 85 | 86 | -------------------------------------------------------------------------------- /FunctionLibrary/pcSpline.m: -------------------------------------------------------------------------------- 1 | function [yNew,d] = pcSpline(xData,yData,xNew) 2 | % xData is assumed to be a uniformly increasing vector and all values 3 | % xNew should be contained in the interval [xData(1),xData(end)] 4 | % Use the piecewise cubic spline formulas defined in interpolation.m 5 | % to compute interpolated values yNew at points xNew 6 | 7 | % %% Ensure that xData and yData are both column vectors 8 | [xRows,~] = size(xData); 9 | [yRows,~] = size(yData); 10 | if xRows == 1 11 | xData = xData'; 12 | end 13 | if yRows == 1 14 | yData = yData'; 15 | end 16 | 17 | % %% Set up the value of n = number of points in xData 18 | 19 | 20 | % %% Calculate the vector of values h tracking the step sizes between 21 | % points in xData 22 | 23 | 24 | % %% Calculate the vector of slopes m tracking the slopes between 25 | % (xData(i),yData(i)) and (xData(i+1),yData(i+1)) 26 | % Remember to use pointwise operations 27 | 28 | 29 | % %% Set up the vector r 30 | % Remember to use pointwise operations 31 | 32 | 33 | % %% Set up the vectors of diagonals for A 34 | mainDiag = ones(1,n); 35 | plus1Diag = mainDiag(1:end-1); 36 | minus1Diag = mainDiag(1:end-1); 37 | 38 | % Set up the values on the main diagonal 39 | 40 | 41 | % Set up the values on the upper diagonal 42 | 43 | 44 | % Set up the values on the lower diagonal 45 | 46 | 47 | % Set up the matrix A as a sparse tridiagonal matrix 48 | A = gallery("tridiag",minus1Diag,mainDiag,plus1Diag); 49 | 50 | % Use matrix operations to solve for the values of d 51 | d = A\r; 52 | 53 | % %% Set up the coefficients for P(x) in each interval where 54 | % xData(k) <= x < xData(k+1) and P_k(x) = a3*s^3+a2*s^2+a1*s+a0 55 | % You may want to check that this is equivalent to the other formulations 56 | % you have seen for the coefficients 57 | a3 = -2*m+d(1:end-1)+d(2:end); 58 | a2 = 3*m-2*d(1:end-1)-d(2:end); 59 | a1 = d(1:end-1); 60 | a0 = yData(1:end-1); 61 | 62 | % %% Initialize the output vector yNew 63 | yNew = nan(size(xNew)); 64 | 65 | % %% Loop over all entries in xNew and compute the interpolated value 66 | for i = 1:length(xNew) 67 | % For each value xNew(i), determine the value k such that 68 | % xData(k) <= xNew(i) < xData(k+1) 69 | j = 1; 70 | while xData(j) <= xNew(i) && j < length(xData) 71 | k=j; 72 | j = j+1; 73 | end 74 | if xNew(i)==xData(end) 75 | yNew(i) = yData(end); 76 | else 77 | % Evaluate the local variables s = xNew(i)-x_k 78 | s = xNew(i)-xData(k); 79 | % Use the polynomial formula P_k(x) to evaluate yNew = P_k(xNew(i)) 80 | yNew(i) = a3(k)*s^3+a2(k)*s^2+a1(k)*s+a0(k); 81 | end 82 | end 83 | end -------------------------------------------------------------------------------- /FunctionLibrary/rk4.m: -------------------------------------------------------------------------------- 1 | function [t,y] = rk4(f,tspan,y0,n) 2 | % rk4 implements a four-step Runge-Kutta method on function f 3 | % over t = tspan(1) to t = tspan(2) where y(tspan(1))=y0 4 | % using n intervals 5 | % 6 | % t is a vector of t values and y is a vector of estimated y(t) values 7 | 8 | % Fill in the details of the implementation here 9 | 10 | end -------------------------------------------------------------------------------- /FunctionLibrary/simpsonsRule.m: -------------------------------------------------------------------------------- 1 | function area = simpsonsRule(f,a,b,n) 2 | % simpsonsRule takes four arguments 3 | % f is a function handle 4 | % a and b are the endpoints of the integral 5 | % n is the number of intervals to use for the approximation 6 | % 7 | % area is the value computed by using a three-point Simpson's rule 8 | % approximation on each subinterval 9 | 10 | % Fill in the details of the implementation here so your 11 | % code will return a correct approximation of the area 12 | area = 0; 13 | 14 | end -------------------------------------------------------------------------------- /Images/AddOnsIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/AddOnsIcon.png -------------------------------------------------------------------------------- /Images/BakerLakeSR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/BakerLakeSR.png -------------------------------------------------------------------------------- /Images/Bird.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/Bird.png -------------------------------------------------------------------------------- /Images/EndIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/EndIcon.png -------------------------------------------------------------------------------- /Images/EulerInt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/EulerInt.png -------------------------------------------------------------------------------- /Images/NoisyDerivative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/NoisyDerivative.png -------------------------------------------------------------------------------- /Images/OpenInFX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/OpenInFX.png -------------------------------------------------------------------------------- /Images/OpenInMO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/OpenInMO.png -------------------------------------------------------------------------------- /Images/StormTrack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/StormTrack.png -------------------------------------------------------------------------------- /Images/TestedWith.json: -------------------------------------------------------------------------------- 1 | {"schemaVersion":1,"label":"Test Status","color":"success","message":"R2024a | R2024b"} 2 | -------------------------------------------------------------------------------- /Images/add-ons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/add-ons.png -------------------------------------------------------------------------------- /Images/eulerMethodDECheck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/eulerMethodDECheck.png -------------------------------------------------------------------------------- /Images/hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/hand.png -------------------------------------------------------------------------------- /Images/heatSoln.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/heatSoln.gif -------------------------------------------------------------------------------- /Images/heatSoln.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/heatSoln.mp4 -------------------------------------------------------------------------------- /Images/image_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/image_11.png -------------------------------------------------------------------------------- /Images/image_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/image_6.png -------------------------------------------------------------------------------- /Images/image_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/image_8.png -------------------------------------------------------------------------------- /Images/pendulum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Images/pendulum.png -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/cnPDESoln.m: -------------------------------------------------------------------------------- 1 | function u = cnPDESoln(f,alpha,beta,tEnd,dx,gamma,L) 2 | % Solve the 1D heat equation u_t = gamma*u_{xx} on a rod of length L 3 | % using the Crank-Nicolson method 4 | % u(t,0) = alpha(t) 5 | % u(t,L) = beta(t) 6 | % u(0,x) = f(x) 7 | % The desired spatial resolution is dx 8 | % Output is u = u(tEnd,x_m), a vector of values on the mesh points 9 | 10 | % Define dt with reference to both error and stability concerns 11 | % Optimal dt for stability 12 | dtOpt = dx; 13 | % Forcing an integer numbers of dt steps that terminate at tEnd 14 | dt = tEnd/ceil(tEnd/dtOpt); 15 | 16 | % % testing %%%%%%%%%% 17 | % dt = 0.005; 18 | 19 | % Set up the helper values for defining the required matrices 20 | numRows = L/dx-1; 21 | mu = gamma*dt/(dx^2); 22 | baseDiag = ones(1,numRows); 23 | 24 | % Define modA for the explicit updating rule 25 | % modA-I = (A-I)/2, where I is the identity matrix 26 | modA = gallery('tridiag',0.5*mu*baseDiag(1:end-1),(1-mu)*baseDiag,0.5*mu*baseDiag(1:end-1)); 27 | 28 | % Define modB for the implicit updating rule 29 | % modB-I = (B-I)/2, where I is the identity matrix 30 | modB = gallery('tridiag',-0.5*mu*baseDiag(1:end-1),(1+mu)*baseDiag,-0.5*mu*baseDiag(1:end-1)); 31 | 32 | % Initialize bAvg = b^(j)+b^(j+1) as a vector of zeros 33 | bAvg = zeros(numRows,1); 34 | 35 | % Define a spatial mesh vector 36 | xVals = linspace(0,L,round(L/dx)+1); 37 | 38 | % Set up a column vector u0 of the initial values of u when t=0 39 | u0 = f(xVals)'; 40 | 41 | % Initialize the output to the interior points of u0 42 | u = u0(2:end-1); 43 | 44 | % To visualize the outputs 45 | p = plot(xVals,u0,"LineWidth",2,"SeriesIndex",1); 46 | ax = p.Parent; 47 | 48 | % Set the y limits to reasonable fixed values 49 | minAlpha = min(alpha(0:dt:tEnd)); 50 | maxAlpha = max(alpha(0:dt:tEnd)); 51 | minBeta = min(beta(0:dt:tEnd)); 52 | maxBeta = max(beta(0:dt:tEnd)); 53 | yLower = min([ax.YLim(1),minAlpha,minBeta]); 54 | yUpper = max([ax.YLim(2),maxAlpha,maxBeta]); 55 | scale = (yUpper-yLower)*0.05; 56 | ax.YLim = [yLower-scale yUpper+scale]; 57 | 58 | title("Solving $\frac{\partial u}{\partial t} = \gamma \frac{\partial^2 u}{\partial x^2}$ with Crank-Nicolson","Interpreter","latex") 59 | subtitle("$t=0$","Interpreter","latex") 60 | xlabel("$x$","Interpreter","latex") 61 | ylabel("$u$","Interpreter","latex") 62 | 63 | % Compute new values for halfB*u^(j+1)-b^(j+1) = halfA*u^(j)+b^(j) 64 | % Loop over timesteps to reach tEnd 65 | for j = 1:(tEnd/dt) 66 | bAvg(1) = mu*(alpha((j-1)*dt)+alpha(j*dt))/2; 67 | bAvg(end) = mu*(beta((j-1)*dt)+beta(j*dt))/2; 68 | u = modB\(modA*u+bAvg); 69 | % To visualize the outputs 70 | hold on 71 | delete(ax.Children(1:end-1)); 72 | plot(xVals,[alpha(j*dt);u;beta(j*dt)],"LineWidth",2,"SeriesIndex",2) 73 | subtitle("$t = $"+dt*j) 74 | drawnow 75 | pause(0.1) 76 | hold off 77 | % End visualization code 78 | end 79 | legend(["u(0,x)","u(t,x)"],"Location","north") 80 | end 81 | -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/cnPDEu0Soln.m: -------------------------------------------------------------------------------- 1 | function u = cnPDE(u0,alpha,beta,tEnd,dx,gamma,L,t0) 2 | % Solve the 1D heat equation u_t = gamma*u_{xx} on a rod of length L 3 | % using the Crank-Nicolson method 4 | % u(t,0) = alpha(t) 5 | % u(t,L) = beta(t) 6 | % u(t0,x) = u0 7 | % The desired spatial resolution is dx 8 | % Output is u = u(tEnd,x_m), a vector of values on the mesh points 9 | 10 | % Define dt with reference to both error and stability concerns 11 | % Optimal dt for stability 12 | dtOpt = dx; 13 | % Forcing an integer numbers of dt steps that terminate at tEnd 14 | dt = tEnd/ceil((tEnd-t0)/dtOpt); 15 | 16 | % % testing %%%%%%%%%% 17 | % dt = 0.005; 18 | 19 | % Set up the helper values for defining the required matrices 20 | numRows = L/dx-1; 21 | mu = gamma*dt/(dx^2); 22 | baseDiag = ones(1,numRows); 23 | 24 | % Define modA for the explicit updating rule 25 | % modA-I = (A-I)/2, where I is the identity matrix 26 | modA = gallery('tridiag',0.5*mu*baseDiag(1:end-1),(1-mu)*baseDiag,0.5*mu*baseDiag(1:end-1)); 27 | 28 | % Define modB for the implicit updating rule 29 | % modB-I = (B-I)/2, where I is the identity matrix 30 | modB = gallery('tridiag',-0.5*mu*baseDiag(1:end-1),(1+mu)*baseDiag,-0.5*mu*baseDiag(1:end-1)); 31 | 32 | % Initialize bAvg = b^(j)+b^(j+1) as a vector of zeros 33 | bAvg = zeros(numRows,1); 34 | 35 | % Define a spatial mesh vector 36 | xVals = linspace(0,L,round(L/dx)+1); 37 | 38 | % Initialize the output to the interior points of u0 39 | u = u0(2:end-1); 40 | 41 | % To visualize the outputs 42 | p = plot(xVals,u0,"LineWidth",4); 43 | ax = p.Parent; 44 | 45 | % Set the y limits to reasonable fixed values 46 | minAlpha = min(alpha(0:dt:tEnd)); 47 | maxAlpha = max(alpha(0:dt:tEnd)); 48 | minBeta = min(beta(0:dt:tEnd)); 49 | maxBeta = max(beta(0:dt:tEnd)); 50 | yLower = min([ax.YLim(1),minAlpha,minBeta]); 51 | yUpper = max([ax.YLim(2),maxAlpha,maxBeta]); 52 | scale = (yUpper-yLower)*0.05; 53 | ax.YLim = [yLower-scale yUpper+scale]; 54 | 55 | title("Solving $\frac{\partial u}{\partial t} = \gamma \frac{\partial^2 u}{\partial x^2}$","Interpreter","latex") 56 | subtitle("$t=0$","Interpreter","latex") 57 | xlabel("$x$","Interpreter","latex") 58 | ylabel("$u$","Interpreter","latex") 59 | 60 | % Compute new values for halfB*u^(j+1)-b^(j+1) = halfA*u^(j)+b^(j) 61 | % Loop over timesteps to reach tEnd 62 | for j = 0:(tEnd/dt - 1) 63 | bAvg(1) = mu*(alpha(j*dt)+alpha((j+1)*dt))/2; 64 | bAvg(end) = mu*(beta(j*dt)+beta((j+1)*dt))/2; 65 | u = modB\(modA*u+bAvg); 66 | % To visualize the outputs 67 | hold on 68 | delete(ax.Children(1:end-1)); 69 | plot(xVals,[alpha((j+1)*dt);u;beta((j+1)*dt)],"LineWidth",4,SeriesIndex="none") 70 | subtitle("$t = $"+dt*(j+1)) 71 | drawnow 72 | pause(0.1) 73 | hold off 74 | % End visualization code 75 | end 76 | 77 | end 78 | -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/eulerBackwardDifferenceSoln.m: -------------------------------------------------------------------------------- 1 | function [tApprox,yApprox]=eulerBackwardDifferenceSoln(f,init,n,h) 2 | % The eulerBackwardDifference function takes four arguments 3 | % f is a function handle, e.g. @(t,y) t.^2.*cos(y) 4 | % init = is the initial value vector [t0 y0] 5 | % h is the step size and 6 | % n is the number of steps to estimate 7 | % 8 | % The function returns two length (n+1) vectors of 9 | % estimated x and y values 10 | 11 | % Initialize the output with the initial value 12 | tApprox = nan(n+1,1); 13 | yApprox = nan(n+1,1); 14 | tApprox(1) = init(1); 15 | yApprox(1) = init(2); 16 | 17 | % Evaluate one step forward using the Euler forward difference method 18 | tApprox(2) = tApprox(1)+h; 19 | yApprox(2) = yApprox(1)+f(tApprox(1),yApprox(1))*h; 20 | 21 | g = @(t,y,yn) y-f(t,y)*h-yn; 22 | 23 | for i = 3:(n+1) 24 | ti = tApprox(i-1)+h; 25 | yn = yApprox(i-1); 26 | gi = @(y) g(ti,y,yn); 27 | yi = fzero(gi,yn); 28 | tApprox(i) = ti; 29 | yApprox(i) = yi; 30 | end 31 | 32 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/eulerMethodDESoln.m: -------------------------------------------------------------------------------- 1 | function [tApprox,yApprox]=eulerMethodDESoln(f,init,n,h) 2 | arguments 3 | f function_handle % derivative dy/dt = f(t,y) 4 | init (1,2) double % initial value [t0 y0] 5 | n (1,1) double {mustBePositive,mustBeInteger} % number of steps 6 | h (1,1) double % step size 7 | end 8 | % f is a function handle, e.g. @(t,y) t.^2.*cos(y) 9 | 10 | % The function returns two length (n+1) vectors of 11 | % estimated x and y values 12 | 13 | % Initialize the output with the initial value 14 | tApprox = nan(n+1,1); 15 | yApprox = nan(n+1,1); 16 | tApprox(1) = init(1); 17 | yApprox(1) = init(2); 18 | 19 | for i = 1:n 20 | xi = tApprox(i)+h; 21 | yi = yApprox(i)+f(tApprox(i),yApprox(i))*h; 22 | tApprox(i+1) = xi; 23 | yApprox(i+1) = yi; 24 | end 25 | 26 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/eulerMethodSoln.m: -------------------------------------------------------------------------------- 1 | function [xApprox,yApprox]=eulerMethodSoln(f,init,n,h) 2 | arguments 3 | f function_handle % integrand, e.g. @(x) x.^2 4 | init (1,2) double % initial value 5 | n (1,1) double {mustBePositive,mustBeInteger} % number of steps 6 | h (1,1) double % step size 7 | end 8 | 9 | % The function returns two length (n+1) vectors of 10 | % estimated x and y values 11 | 12 | % Initialize the output with the initial value 13 | xApprox = nan(n+1,1); 14 | yApprox = nan(n+1,1); 15 | xApprox(1) = init(1); 16 | yApprox(1) = init(2); 17 | 18 | for i = 1:n 19 | xi = xApprox(i)+h; 20 | yi = yApprox(i)+f(xApprox(i))*h; 21 | xApprox(i+1) = xi; 22 | yApprox(i+1) = yi; 23 | end 24 | 25 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/explicitPDESoln.m: -------------------------------------------------------------------------------- 1 | function u = explicitPDESoln(f,alpha,beta,tEnd,dx,gamma,L) 2 | % Solve the 1D heat equation u_t = gamma*u_{xx} on a rod of length L 3 | % u(t,0) = alpha(t) 4 | % u(t,L) = beta(t) 5 | % u(0,x) = f(x) 6 | % The desired spatial resolution is dx 7 | % Output is u = u(tEnd,x_m), a vector of values on the mesh points 8 | 9 | % Define dt with reference to both error and stability concerns 10 | % Optimal dt for stability 11 | dtOpt = dx^2/(2*gamma); 12 | % Forcing an integer numbers of dt steps that terminate at tEnd 13 | dt = tEnd/ceil(tEnd/dtOpt); 14 | 15 | % % testing %%%%%%%%%% 16 | % dt = 0.005; 17 | 18 | % Define helper values 19 | numRows = L/dx-1; 20 | mu = gamma*dt/(dx^2); 21 | baseDiag = ones(1,numRows); 22 | 23 | % Define A for the updating rule 24 | % u^(j+1) = A*u^(j)+b^(j) 25 | A = gallery('tridiag',mu*baseDiag(1:end-1),(1-2*mu)*baseDiag,mu*baseDiag(1:end-1)); 26 | 27 | % Initialize b as a vector of zeros 28 | b = zeros(numRows,1); 29 | 30 | % Define a spatial mesh vector 31 | xVals = linspace(0,L,round(L/dx)+1); 32 | 33 | % Set up a column vector u0 of the initial values of u when t=0 34 | u0 = (f(xVals))'; 35 | 36 | % Initialize the output to the interior points of u0 37 | u = u0(2:end-1); 38 | 39 | % To visualize the outputs 40 | p = plot(xVals,u0,"LineWidth",4); 41 | ax = p.Parent; 42 | 43 | % Set the y limits to reasonable fixed values 44 | minAlpha = min(alpha(0:dt:tEnd)); 45 | maxAlpha = max(alpha(0:dt:tEnd)); 46 | minBeta = min(beta(0:dt:tEnd)); 47 | maxBeta = max(beta(0:dt:tEnd)); 48 | yLower = min([ax.YLim(1),minAlpha,minBeta]); 49 | yUpper = max([ax.YLim(2),maxAlpha,maxBeta]); 50 | scale = (yUpper-yLower)*0.05; 51 | ax.YLim = [yLower-scale yUpper+scale]; 52 | 53 | title("Solving $\frac{\partial u}{\partial t} = \gamma \frac{\partial^2 u}{\partial x^2}$ explicitly","Interpreter","latex") 54 | subtitle("$t=0$","Interpreter","latex") 55 | xlabel("$x$","Interpreter","latex") 56 | ylabel("$u$","Interpreter","latex") 57 | 58 | % Compute new values for u^(j+1) = Au^(j)+b^(j) 59 | % Loop over timesteps to reach tEnd 60 | for j = 0:(tEnd/dt - 1) 61 | b(1) = alpha(j*dt); 62 | b(end) = beta(j*dt); 63 | u = A*u+b; 64 | % To visualize the outputs 65 | hold on 66 | delete(ax.Children(1:end-1)); 67 | plot(xVals,[alpha((j+1)*dt);u;beta((j+1)*dt)],"SeriesIndex",2,"LineWidth",4) 68 | subtitle("$t = $"+dt*(j+1)) 69 | drawnow 70 | pause(0.1) 71 | hold off 72 | % End visualization code 73 | end 74 | 75 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/gauss2ptSoln.m: -------------------------------------------------------------------------------- 1 | function Fapprox = gauss2ptSoln(f,a,b) 2 | % gauss2pt takes three arguments 3 | % f is a function handle 4 | % a and b are the bounds of a definite integral 5 | % 6 | % Fapprox returns the Gaussian 2 point approximation of the 7 | % integral from a to b of f(x) dx 8 | w1 = 1; 9 | w2 = 1; 10 | x1 = -1/sqrt(3); 11 | x2 = 1/sqrt(3); 12 | 13 | % Change variables from [-1,1] to [a,b] 14 | scaledWeights = (b-a)/2*[w1 w2]; 15 | scaledX = (b-a)/2*[x1; x2]+(b+a)/2; 16 | 17 | Fapprox = scaledWeights*f(scaledX); 18 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/implicitPDESoln.m: -------------------------------------------------------------------------------- 1 | function u = implicitPDESoln(f,alpha,beta,tEnd,dx,gamma,L) 2 | % Solve the 1D heat equation u_t = gamma*u_{xx} on a rod of length L 3 | % u(t,0) = alpha(t) 4 | % u(t,L) = beta(t) 5 | % u(0,x) = f(x) 6 | % The desired spatial resolution is dx 7 | % Output is u = u(tEnd,x_m), a vector of values on the mesh points 8 | 9 | 10 | % Define dt with reference to both error and stability concerns 11 | % Optimal dt for stability 12 | dtOpt = dx^2; 13 | % Forcing an integer numbers of dt steps that terminate at tEnd 14 | dt = tEnd/ceil(tEnd/dtOpt); 15 | 16 | % % testing %%%%%%%%%% 17 | % dt = 0.005; 18 | 19 | % Define B for the updating rule 20 | % Bu^(j+1)-b^(j+1) = u^(j) 21 | numRows = L/dx-1; 22 | mu = gamma*dt/(dx^2); 23 | baseDiag = ones(1,numRows); 24 | B = gallery('tridiag',-mu*baseDiag(1:end-1),(1+2*mu)*baseDiag,-mu*baseDiag(1:end-1)); 25 | 26 | % Initialize b as a vector of zeros 27 | b = zeros(numRows,1); 28 | 29 | % Define a spatial mesh vector 30 | xVals = linspace(0,L,round(L/dx)+1); 31 | 32 | % Set up a column vector u0 of the initial values of u when t=0 33 | u0 = (f(xVals))'; 34 | 35 | % Initialize the output to the interior points of u0 36 | u = u0(2:end-1); 37 | 38 | % To visualize the outputs 39 | p = plot(xVals,u0,"LineWidth",4); 40 | ax = p.Parent; 41 | 42 | % Set the y limits to reasonable fixed values 43 | minAlpha = min(alpha(0:dt:tEnd)); 44 | maxAlpha = max(alpha(0:dt:tEnd)); 45 | minBeta = min(beta(0:dt:tEnd)); 46 | maxBeta = max(beta(0:dt:tEnd)); 47 | yLower = min([ax.YLim(1),minAlpha,minBeta]); 48 | yUpper = max([ax.YLim(2),maxAlpha,maxBeta]); 49 | scale = (yUpper-yLower)*0.05; 50 | ax.YLim = [yLower-scale yUpper+scale]; 51 | 52 | title("Solving $\frac{\partial u}{\partial t} = \gamma \frac{\partial^2 u}{\partial x^2}$ implicitly","Interpreter","latex") 53 | subtitle("$t=0$","Interpreter","latex") 54 | xlabel("$x$","Interpreter","latex") 55 | ylabel("$u$","Interpreter","latex") 56 | 57 | % Compute new values for B*u^(j+1) - b^(j+1) = Au^(j) 58 | % Loop over timesteps to reach tEnd 59 | for j = 0:(tEnd/dt - 1) 60 | b(1) = alpha((j+1)*dt); 61 | b(end) = beta((j+1)*dt); 62 | u = B\(u+b); 63 | % To visualize the outputs 64 | hold on 65 | delete(ax.Children(1:end-1)); 66 | plot(xVals,[alpha((j+1)*dt);u;beta((j+1)*dt)],"LineWidth",4,SeriesIndex="none") 67 | subtitle("$t = $"+dt*(j+1)) 68 | drawnow 69 | pause(0.1) 70 | hold off 71 | % End visualization code 72 | end 73 | 74 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/improvedEulerSoln.m: -------------------------------------------------------------------------------- 1 | function [tApprox,yApprox]=improvedEulerSoln(f,init,n,h) 2 | % The improvedEuler function takes four arguments 3 | % f is a function handle, e.g. @(t,y) t.^2.*cos(y) 4 | % init = is the initial value vector [t0 y0] 5 | % h is the step size and 6 | % n is the number of steps to estimate 7 | % 8 | % The function returns two length (n+1) vectors of 9 | % estimated x and y values 10 | 11 | % This method is also called the Heun formula 12 | 13 | % Initialize the output with the initial value 14 | tApprox = nan(n+1,1); 15 | yApprox = nan(n+1,1); 16 | tApprox(1) = init(1); 17 | yApprox(1) = init(2); 18 | 19 | 20 | for i = 2:(n+1) 21 | tPrev = tApprox(i-1); 22 | ti = tPrev+h; 23 | yPrev = yApprox(i-1); 24 | yiGuess = yPrev+f(tPrev,yPrev)*h; 25 | yiImproved = (yiGuess+yPrev+f(ti,yiGuess)*h)/2; 26 | tApprox(i) = ti; 27 | yApprox(i) = yiImproved; 28 | end 29 | 30 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/linInterpSimpSoln.m: -------------------------------------------------------------------------------- 1 | function yNew = linInterpSimp(xData,yData,xNew) 2 | % linInterp interpolates the point(s) (xNew(i),yNew(i)) using a 3 | % piecewise linear interpolation on the input data xData 4 | % and output data yData 5 | 6 | % Initialize output values vector 7 | yNew = nan(size(xNew)); 8 | 9 | % Is xData decreasing? 10 | if xData(2)-xData(1) < 0 11 | % Reorder xData and yData so that xData is increasing 12 | xData = xData(end:-1:1); 13 | yData = yData(end:-1:1); 14 | end 15 | 16 | % Check each value in xNew and determine its 17 | % corresponding interpolated value in yNew 18 | for k = 1:length(xNew) 19 | curVal = xNew(k); 20 | for j = 1:length(xData)-1 21 | if curVal == xData(j) 22 | yNew(k) = yData(j); 23 | elseif (xData(j) < curVal) && (curVal < xData(j+1)) 24 | yNew(k) = yData(j) + (curVal - xData(j))*(yData(j+1)-yData(j))/(xData(j+1)-xData(j)); 25 | end 26 | end 27 | if curVal == xData(end) 28 | yNew = yData(end); 29 | end 30 | end 31 | 32 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/linInterpSoln.m: -------------------------------------------------------------------------------- 1 | function yNew = linInterp(xData,yData,xNew) 2 | % linInterp interpolates the point(s) (xNew(i),yNew(i)) using a 3 | % piecewise linear interpolation on the input data xData 4 | % and output data yData 5 | 6 | % Initialize output values vector 7 | yNew = nan(size(xNew)); 8 | 9 | % Check whether the input values make sense and have the expected shape 10 | if isvector(xData) && isvector(xNew) 11 | % Ensure that xData is a row vector 12 | if ~isrow(xData) 13 | xData = xData'; 14 | end 15 | 16 | % Ensure that xNew is a row vector 17 | if ~isrow(xNew) 18 | xNew = xNew'; 19 | end 20 | else 21 | warning("The input data must be vectors.") 22 | return 23 | end 24 | 25 | if max(xNew)>max(xData) || min(xNew)0) == length(xData)-1 36 | % xData is increasing 37 | flag = 1; 38 | elseif nnz(diff(xData)<0) == length(xData)-1 39 | % xData is decreasing 40 | flag = -1; 41 | else 42 | warning("The input data is not properly ordered. " + ... 43 | "The xData must be monotonic.") 44 | return 45 | end 46 | 47 | % Find the closest datapoint in xData for each value xNew 48 | [distVal,idx] = min((xNew'-xData).^2,[],2); 49 | midIdx = distVal~=0; 50 | 51 | % Calculate the values of yNew that occur on values of yData 52 | yNew(~midIdx) = yData(idx(~midIdx)); 53 | 54 | % Identify the indices of the endpoints of the relevant interval for 55 | % non-endpoint values of xNew 56 | altEndPt = sign((xNew(midIdx)-xData(idx(midIdx))).*flag); 57 | 58 | % if max(idx(altEndPt==0))< length(xData) 59 | % altEndPt(altEndPt==0) = 1; 60 | % elseif min(idx(altEndPt==0))< length(xData) 61 | rowIdx = idx'; 62 | endIdx = sort([rowIdx(midIdx);rowIdx(midIdx)+altEndPt]); 63 | 64 | % Compute the x and y values of the endpoints 65 | endxLeft = xData(endIdx(1,:)); 66 | endxRight = xData(endIdx(2,:)); 67 | endyLeft = yData(endIdx(1,:)); 68 | endyRight = yData(endIdx(2,:)); 69 | 70 | 71 | % Use point-slope form to evaluate yNew on intervior points 72 | % y = y_1 + m*(x-x_1) 73 | yNew(midIdx) = endyLeft + (endyRight-endyLeft)./(endxRight-endxLeft)... 74 | .*(xNew(midIdx)-endxLeft); 75 | 76 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/pcHInterpSoln.m: -------------------------------------------------------------------------------- 1 | function yNew = pcHInterpSoln(xData,yData,xNew) 2 | % xData is assumed to be a uniformly increasing vector and all values 3 | % xNew should be contained in the interval [xData(1),xData(end)] 4 | % Use the piecewise cubic spline formulas defined in interpolation.m 5 | % to compute interpolated values yNew at points xNew 6 | 7 | % %% Ensure that xData and yData are column vectors 8 | [xRows,~] = size(xData); 9 | [yRows,~] = size(yData); 10 | if xRows == 1 11 | xData = xData'; 12 | end 13 | if yRows == 1 14 | yData = yData'; 15 | end 16 | 17 | % %% Set up the value of n = number of intervals between points in xData 18 | n = length(xData); 19 | 20 | % %% Calculate the vector of values h where 21 | % h(i) = h_i = xData(i+1)-xData(i) 22 | h = xData(2:end)-xData(1:end-1); 23 | 24 | % %% Calculate the vector of slopes m where 25 | % m(i) = m_i = (y_(i+1)-y_i)/h(i) 26 | % Remember to use pointwise operations 27 | m = (yData(2:end)-yData(1:end-1))./h; 28 | 29 | % %% Determine the values of the slopes for the interpolant 30 | d = nan(n,1); 31 | % %% Start by calculating the slopes at interior points 32 | % If the sign of the slope changes between xData(i-1) and xData(i+1), or 33 | % if the slope is 0 in interval i-1 or i, set d(i) to be 0. 34 | % Otherwise, use a weighted centered difference approximation 35 | % where (w1+w2)/d(i) = w1/m(i-1)+w2/m(i) 36 | % with w1 = 2*h(i)+h(i-1) and w2 = 2*h(i-1)+h(i) 37 | for i = 2:n-1 38 | if m(i-1) == 0 || m(i)/m(i-1) <= 0 39 | % Check for local minima or maxima 40 | d(i) = 0; 41 | else 42 | % Compute weights 43 | w1 = 2*h(i)+h(i-1); 44 | w2 = 2*h(i-1)+h(i); 45 | d(i) = (w1+w2)/(w1/m(i-1)+w2/m(i)); 46 | end 47 | end 48 | 49 | % Add the slopes at i=1 and i=n using the formula 50 | % ((2*h1+h2)*m1-h1*m2)/(h1+h2) where 51 | % h1 is the length of the first step back/forward and 52 | % h2 is the length of the second step back/foward and 53 | % m1 is the slope over the first interval back/forward and 54 | % m2 is the slope over the second interval back/forward 55 | d(1) = ((2*h(1)+h(2))*m(1)-h(1)*m(2))/(h(1)+h(2)); 56 | d(n) = ((2*h(n-1)+h(n-2))*m(n-1)-h(n-1)*m(n-2))/(h(n-1)+h(n-2)); 57 | 58 | d(1) = checkOvershoot(d(1),m(1),m(2)); 59 | d(n) = checkOvershoot(d(n),m(n-1),m(n-2)); 60 | 61 | % %% Set up the coefficients for P(x) in each interval where 62 | % xData(k) <= x < xData(k+1) and P_k(x) = a3*s^3+a2*s^2+a1*s+a0 63 | a3 = -2*m+d(1:end-1)+d(2:end); 64 | a2 = 3*m-2*d(1:end-1)-d(2:end); 65 | a1 = d(1:end-1); 66 | a0 = yData(1:end-1); 67 | 68 | % %% Initialize the output vector yNew 69 | yNew = nan(size(xNew)); 70 | 71 | % %% Loop over all entries in xNew and compute the interpolated value 72 | for i = 1:length(xNew) 73 | % For each value xNew(i), determine the value k such that 74 | % xData(k) <= xNew(i) < xData(k+1) 75 | j = 1; 76 | while xData(j) <= xNew(i) && j < length(xData) 77 | k=j; 78 | j = j+1; 79 | end 80 | if xNew(i)==xData(end) 81 | yNew(i) = yData(end); 82 | else 83 | % Evaluate the local variables s = xNew(i)-x_k 84 | s = xNew(i)-xData(k); 85 | % Use the polynomial formula P_k(x) to evaluate yNew = P_k(xNew(i)) 86 | yNew(i) = a3(k)*s^3+a2(k)*s^2+a1(k)*s+a0(k); 87 | end 88 | end 89 | end 90 | function d = checkOvershoot(d,m1,m2) 91 | if sign(d) ~= sign(m1) 92 | d=0; 93 | elseif sign(d) ~= sign(m2) & (abs(d)>abs(3*m1)) 94 | d = 3*m1; 95 | end 96 | end 97 | 98 | -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/pcSplineSoln.m: -------------------------------------------------------------------------------- 1 | function [yNew,d] = pcSplineSoln(xData,yData,xNew) 2 | % xData is assumed to be a uniformly increasing vector and all values 3 | % xNew should be contained in the interval [xData(1),xData(end)] 4 | % Use the piecewise cubic spline formulas defined in interpolation.m 5 | % to compute interpolated values yNew at points xNew 6 | 7 | % %% Ensure that xData and yData are both column vectors 8 | [xRows,~] = size(xData); 9 | [yRows,~] = size(yData); 10 | if xRows == 1 11 | xData = xData'; 12 | end 13 | if yRows == 1 14 | yData = yData'; 15 | end 16 | 17 | % %% Set up the value of n = number of points in xData 18 | n = length(xData); 19 | 20 | % %% Calculate the vector of values h where 21 | % h(i) = h_i = xData(i+1)-xData(i) 22 | h = xData(2:end)-xData(1:end-1); 23 | 24 | % %% Calculate the vector of slopes m where 25 | % m(i) = m_i = (y_(i+1)-y_i)/h(i) 26 | % Remember to use pointwise operations 27 | m = (yData(2:end)-yData(1:end-1))./h; 28 | 29 | % %% Set up the vector r 30 | % r(1) = 5/2m_1 + 1/2m_2 and r(n) = 1/2m_(n-2)+5/2m_n-1 31 | % with the middle values all given by 32 | % r(i) = 3*(h(i)m(i-1)+h(i-1)*m(i)) 33 | % Remember to use pointwise operations 34 | r = nan(n,1); 35 | r(1) = 5/2*m(1)+m(2)/2; 36 | r(n) = m(n-2)/2+5/2*m(n-1); 37 | r(2:n-1) = 3*(h(2:n-1).*m(1:n-2)+h(1:n-2).*m(2:n-1)); 38 | 39 | 40 | % %% Set up the vectors of diagonals for A 41 | mainDiag = ones(1,n); 42 | plus1Diag = mainDiag(1:end-1); 43 | minus1Diag = mainDiag(1:end-1); 44 | 45 | % mainDiag(1) = h_2 and mainDiag(n) = h_(n-2) 46 | % with the middle values all given by 47 | % mainDiag(i) = 2(h_(i-1)+h_i) 48 | mainDiag(1) = h(2); 49 | mainDiag(n) = h(n-2); 50 | mainDiag(2:n-1) = 2*(h(1:n-2)+h(2:n-1)); 51 | 52 | % plus1Diag(1) = h_2+h_1 and plus1Diag(i) = h_(i-1) 53 | plus1Diag(1) = h(2)+h(1); 54 | plus1Diag(2:end) = h(1:n-2); 55 | % minus1Diag(n-1) = h_(n-1)+h_(n-2) and minus1Diag(i) = h_(i+1) 56 | minus1Diag(n-1) = h(n-1)+h(n-2); 57 | minus1Diag(1:end-1) = h(2:n-1); 58 | 59 | % Set up the matrix A as a sparse tridiagonal matrix 60 | A = gallery("tridiag",minus1Diag,mainDiag,plus1Diag); 61 | 62 | % Use matrix operations to solve for the values of d 63 | d = A\r; 64 | 65 | % %% Set up the coefficients for P(x) in each interval where 66 | % xData(k) <= x < xData(k+1) and P_k(x) = a3*s^3+a2*s^2+a1*s+a0 67 | a3 = -2*m+d(1:end-1)+d(2:end); 68 | a2 = 3*m-2*d(1:end-1)-d(2:end); 69 | a1 = d(1:end-1); 70 | a0 = yData(1:end-1); 71 | 72 | % %% Initialize the output vector yNew 73 | yNew = nan(size(xNew)); 74 | 75 | % %% Loop over all entries in xNew and compute the interpolated value 76 | for i = 1:length(xNew) 77 | % For each value xNew(i), determine the value k such that 78 | % xData(k) <= xNew(i) < xData(k+1) 79 | j = 1; 80 | while xData(j) <= xNew(i) && j < length(xData) 81 | k=j; 82 | j = j+1; 83 | end 84 | if xNew(i)==xData(end) 85 | yNew(i) = yData(end); 86 | else 87 | % Evaluate the local variables s = xNew(i)-x_k 88 | s = xNew(i)-xData(k); 89 | % Use the polynomial formula P_k(x) to evaluate yNew = P_k(xNew(i)) 90 | yNew(i) = a3(k)*s^3+a2(k)*s^2+a1(k)*s+a0(k); 91 | end 92 | end 93 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/rk4Soln.m: -------------------------------------------------------------------------------- 1 | function [t,y] = rk4Soln(f,tspan,y0,n) 2 | % rk4 implements a four-step Runge-Kutta method on function f 3 | % over t = tspan(1) to t = tspan(2) where y(tspan(1))=y0 4 | % using n intervals 5 | % 6 | % t is a vector of t values and y is a vector of estimated y(t) values 7 | 8 | t = (linspace(tspan(1),tspan(2),n+1))'; 9 | 10 | y = nan(n+1,1); 11 | 12 | y(1) = y0; 13 | 14 | for i = 1:n 15 | tLeft = t(i); 16 | tRight = t(i+1); 17 | tMid = (tLeft+tRight)/2; 18 | yLeft = y(i); 19 | h = t(i+1)-t(i); 20 | k1 = f(tLeft,yLeft); 21 | k2 = f(tMid,yLeft+0.5*h*k1); 22 | k3 = f(tMid,yLeft+0.5*h*k2); 23 | k4 = f(tRight,yLeft+h*k3); 24 | y(i+1) = yLeft + (h/6)*(k1+2*k2+2*k3+k4); 25 | end 26 | 27 | end 28 | -------------------------------------------------------------------------------- /InstructorResources/Solutions/FunctionLibrarySolutions/simpsonsRuleSoln.m: -------------------------------------------------------------------------------- 1 | function area = simpsonsRuleSoln(f,a,b,n) 2 | % simpsonsRule takes four arguments 3 | % f is a function handle 4 | % a and b are the endpoints of the integral 5 | % n is the number of intervals to use for the approximation 6 | % 7 | % area is the value computed by using a three-point Simpson's rule 8 | % approximation on each subinterval 9 | 10 | % Discretize the function on the endpoints of the intervals 11 | endPts = linspace(a,b,n+1); 12 | fEndpts = f(endPts); 13 | 14 | % Discretize the function on the midpoints of the intervals 15 | midPts = (endPts(2:end)+endPts(1:end-1))/2; 16 | fMidpts = f(midPts); 17 | 18 | % Combine the terms via the (h/3)*(f(a) + 4*f((b+a)/2) + f(b)) 19 | area = (b-a)/(6*n)*(sum(fEndpts) + sum(fEndpts(2:end-1)) + 4*sum(fMidpts)); 20 | 21 | 22 | end -------------------------------------------------------------------------------- /InstructorResources/Solutions/HandSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/HandSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/ImplementExplicitSolverSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/ImplementExplicitSolverSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/InterpolationSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/InterpolationSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/MeasureLakeAreaSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/MeasureLakeAreaSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/NumericalDerivativesSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/NumericalDerivativesSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/NumericalIntegrationSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/NumericalIntegrationSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/NumericalODEsSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/NumericalODEsSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/NumericalPDEsSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/NumericalPDEsSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/PendulumModelsSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/PendulumModelsSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/TrackStormsSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/TrackStormsSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/myLakeData.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/myLakeData.mat -------------------------------------------------------------------------------- /InstructorResources/Solutions/myModernLakeData.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/InstructorResources/Solutions/myModernLakeData.mat -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024, The MathWorks, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the distribution 13 | * Neither the name of the The MathWorks, Inc. nor the names 14 | of its contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /MainMenu.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/MainMenu.mlx -------------------------------------------------------------------------------- /NumericalMethods.prj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Numerical Methods with Applications 3 | 4 | 5 | [![View on File Exchange](https://www.mathworks.com/matlabcentral/images/matlab-file-exchange.svg)](https://www.mathworks.com/matlabcentral/fileexchange/111490-numerical-methods-with-applications) or [![Open in MATLAB Online](https://www.mathworks.com/images/responsive/global/open-in-matlab-online.svg)](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=README.mlx) 6 | 7 | ![MATLAB Versions Tested](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2FMathWorks-Teaching-Resources%2FNumerical-Methods-with-Applications%2Frelease%2FImages%2FTestedWith.json) 8 | 9 | **Curriculum Module** 10 | 11 | _Created with R2021b. Compatible with R2021b and later releases._ 12 | 13 | # Information 14 | 15 | This curriculum module contains interactive [MATLAB® live scripts](https://www.mathworks.com/products/matlab/live-editor.html) that teach fundamental concepts and basic terminology related to designing and implementing numerical methods related to interpolation, numerical integration and differentiation, and numerical solutions to ordinary and partial differential equations. 16 | 17 | ## Background 18 | 19 | You can use these live scripts as demonstrations in lectures, class activities, or interactive assignments outside class. This module addresses standard topics from a first course in numerical methods including interpolation, numerical integration and derivation, and several numerical solution methods for ODEs and PDEs. 20 | 21 | 22 | The instructions inside the live scripts will guide you through the exercises and activities. Get started with each live script by running it one section at a time. To stop running the script or a section midway (for example, when an animation is in progress), use the EndIcon.png Stop button in the **RUN** section of the **Live Editor** tab in the MATLAB Toolstrip. 23 | 24 | ## Contact Us 25 | 26 | Solutions are available upon instructor request. Contact the [MathWorks teaching resources team](mailto:onlineteaching@mathworks.com) if you would like to request solutions, provide feedback, or if you have a question. 27 | 28 | ## Prerequisites 29 | 30 | This module assumes familiarity with basic programming concepts such as floating\-point doubles and strings, structures including constants, vectors, matrices, arrays, control flows including if/else, for loops, and while loops, and how to use them in MATLAB. These ideas are all presented with interactive examples in [Fundamentals of Programming](https://www.mathworks.com/matlabcentral/fileexchange/103225-fundamentals-of-programming). This module assumes familiarity with polynomials, derivatives, and integrals. To use the partial differential equation scripts, a student must be familiar with the concepts of partial derivatives and multivariable functions. These scripts do not assume knowledge of analytic solutions to ordinary or partial differential equations. 31 | 32 | ## Getting Started 33 | ### Accessing the Module 34 | ### **On MATLAB Online:** 35 | 36 | Use the [OpenInMO.png](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj) link to download the module. You will be prompted to log in or create a MathWorks account. The project will be loaded, and you will see an app with several navigation options to get you started. 37 | 38 | ### **On Desktop:** 39 | 40 | Download or clone this repository. Open MATLAB, navigate to the folder containing these scripts and double\-click on [NumerialMethods.prj](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj). It will add the appropriate files to your MATLAB path and open an app that asks you where you would like to start. 41 | 42 | 43 | Ensure you have all the required products (listed below) installed. If you need to include a product, add it using the Add\-On Explorer. To install an add\-on, go to the **Home** tab and select AddOnsIcon.png **Add-Ons** > **Get Add-Ons**. 44 | 45 | 46 | ## Products 47 | 48 | MATLAB® is used throughout. Tools from the Symbolic Math Toolbox™ are used frequently as well. 49 | 50 | - drawpolygon from Image Processing and Computer Vision™ is used to create datasets in Hand.mlx and MeasureLakeArea.mlx 51 | - Statistics and Machine Learning Toolbox™ and the Curve Fitting Toolbox™ are used in Interpolation.mlx 52 | - geoplayer from Automated Driving Toolbox™ is used in TrackStorms.mlx to create elegant visualizations, but pedagogically similar plots are demonstrated with geoplot as well. 53 | 54 | # Scripts 55 | ## [**Interpolation.mlx**](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=Interpolation.mlx) 56 | | hand.png
| **In this script, students will...**

- define interpolation and explain how it is different from regression and extrapolation

- demonstrate multiple solutions to an interpolation problem, even when interpolating by polynomials

- implement three different interpolation functions
| **Applications**

- Drawing a smooth rendition of their hand

- Tracking the path of a cyclone
**Scaffolded Template Scripts**
[linInterp.m](./FunctionLibrary/linInterp.m)
[pcHInterp.m](./FunctionLibrary/pcHInterp.m)
[pcSpline.m](./FunctionLibrary/pcSpline.m)
| 57 | | :-- | :-- | :-- | 58 | 59 | ## Supporting Scripts 60 | - [Hand.mlx](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=Hand.mlx) 61 | - [TrackStorms.mlx](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=TrackStorms.mlx) 62 | ## [**NumericalDerivatives.mlx**](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=NumericalDerivatives.mlx) 63 | | NoisyDerivative.png
| **In this script, students will...**

- determine numerical derivative approximations formulas

- use Taylor's theorem to calculate the order of the error for a numerical approximation to a derivative

- demonstrate how numerical derivatives can magnify approximation errors
| **Applications**

- Numerical solutions to differential equations
| 64 | | :-- | :-- | :-- | 65 | 66 | ## [**NumericalIntegration.mlx**](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=NumericalIntegration.mlx) 67 | | BakerLakeSR.png
| **In this script, students will...**

- implement Euler's method, Gaussian 2\-point approximations, and Simpson's rule for numerical integration

- explain why higher\-order approximations may not be appropriate in applications
| **Applications**

- Measure the area of a lake
**Scaffolded Template Scripts**
[eulerMethod.m](./FunctionLibrary/eulerMethod.m)
[gauss2pt.m](./FunctionLibrary/gauss2pt.m)
[simpsonsRule.m](./FunctionLibrary/simpsonsRule.m)
| 68 | | :-- | :-- | :-- | 69 | 70 | ## Supporting Scripts 71 | - [MeasureLakeArea.mlx](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=MeasureLakeArea.mlx) 72 | ## [**NumericalODEs.mlx**](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=NumericalODEs.mlx) 73 | | image_6.png
| **In this script, students will...**

- implement Euler's method for first\-order initial value problems

- calculate the error of their numerical solution

- implement a trapezoidal method

- implement a four\-step Runge\-Kutta method

- compare results with the built\-in MATLAB solver ode45
| **Applications**

- Model a pendulum with increasingly realistic assumptions
**Scaffolded Template Scripts**
[eulerMethodDE.m](./FunctionLibrary/eulerMethodDE.m)
[rk4.m](./FunctionLibrary/rk4.m)
| 74 | | :-- | :-- | :-- | 75 | 76 | ## Supporting Scripts 77 | - [PendulumModels.mlx](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=PendulumModels.mlx) 78 | ## [**NumericalPDEs.mlx**](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Numerical-Methods-with-Applications&project=NumericalMethods.prj&file=NumericalPDEs.mlx) 79 | | heatSoln.gif
| **In this script, students will...**

- identify errors from discretizing the problem and from discretizing the method and choose appropriate parameters to minimize overall error

- explain the importance of stability when choosing a numerical method

- implement explicit, implicit, and Crank\-Nicolson methods to solve a 1\-D heat equation
| **Applications**

- Solve a heat equation
**Scaffolded Template Scripts**
[explicitPDE.m](./FunctionLibrary/explicitPDE.m)
[implicitPDE.m](./FunctionLibrary/implicitPDE.m)
[cnPDE.m](./FunctionLibrary/cnPDE.m)
| 80 | | :-- | :-- | :-- | 81 | 82 | # License 83 | 84 | The license for this module is available in the [LICENSE.md](https://github.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/blob/release/LICENSE.md). 85 | 86 | # Related Courseware Modules 87 | | **Courseware Module**
| **Sample Content**
| **Available on:**
| 88 | | :-- | :-- | :-- | 89 | | [**Applied Linear Algebra**](https://www.mathworks.com/matlabcentral/fileexchange/136364-applied-linear-algebra)
| image_8.png
| [OpenInFX.png](https://www.mathworks.com/matlabcentral/fileexchange/136364-applied-linear-algebra)
[OpenInMO.png](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Applied-Linear-Algebra&project=AppliedLinAlg.prj)
[GitHub](https://github.com/MathWorks-Teaching-Resources/Applied-Linear-Algebra)
| 90 | |
[**Programming: Structuring Code**](https://www.mathworks.com/matlabcentral/fileexchange/115905-programming-structuring-code)
Learn how to organize your code into functions,
debug, comment, and share
| image_11.png
|
[OpenInFX.png](https://www.mathworks.com/matlabcentral/fileexchange/115905-programming-structuring-code)

[OpenInMO.png](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-Structuring-Code&project=StructuringCode.prj)

[GitHub](https://github.com/MathWorks-Teaching-Resources/Programming-Structuring-Code)
| 91 | 92 | 93 | Or feel free to explore our other [modular courseware content](https://www.mathworks.com/matlabcentral/fileexchange/?q=tag%3A%22courseware+module%22&sort=downloads_desc_30d). 94 | 95 | # Educator Resources 96 | - [Educator Page](https://www.mathworks.com/academia/educators.html) 97 | 98 | # Contribute 99 | 100 | Looking for more? Find an issue? Have a suggestion? Please contact the [MathWorks teaching resources team](mailto:%20onlineteaching@mathworks.com). If you want to contribute directly to this project, you can find information about how to do so in the [CONTRIBUTING.md](https://github.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/blob/release/CONTRIBUTING.md) page on GitHub. 101 | 102 | 103 | *©* Copyright 2024 The MathWorks™, Inc 104 | 105 | 106 | -------------------------------------------------------------------------------- /README.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/README.mlx -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Vulnerabilities 2 | 3 | If you believe you have discovered a security vulnerability, please report it to 4 | [security@mathworks.com](mailto:security@mathworks.com). Please see 5 | [MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html) 6 | for additional information. -------------------------------------------------------------------------------- /Scripts/Hand.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/Hand.mlx -------------------------------------------------------------------------------- /Scripts/ImplementExplicitSolver.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/ImplementExplicitSolver.mlx -------------------------------------------------------------------------------- /Scripts/Interpolation.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/Interpolation.mlx -------------------------------------------------------------------------------- /Scripts/MeasureLakeArea.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/MeasureLakeArea.mlx -------------------------------------------------------------------------------- /Scripts/NumericalDerivatives.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/NumericalDerivatives.mlx -------------------------------------------------------------------------------- /Scripts/NumericalIntegration.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/NumericalIntegration.mlx -------------------------------------------------------------------------------- /Scripts/NumericalODEs.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/NumericalODEs.mlx -------------------------------------------------------------------------------- /Scripts/NumericalPDEs.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/NumericalPDEs.mlx -------------------------------------------------------------------------------- /Scripts/PendulumModels.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/PendulumModels.mlx -------------------------------------------------------------------------------- /Scripts/TrackStorms.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/Scripts/TrackStorms.mlx -------------------------------------------------------------------------------- /SoftwareTests/CheckTestResults.m: -------------------------------------------------------------------------------- 1 | classdef CheckTestResults < matlab.unittest.TestCase 2 | 3 | properties (SetAccess = protected) 4 | end 5 | 6 | properties (ClassSetupParameter) 7 | Project = {currentProject()}; 8 | end 9 | 10 | properties (TestParameter) 11 | Version 12 | end 13 | 14 | 15 | methods (TestParameterDefinition,Static) 16 | 17 | function Version = GetResults(Project) 18 | RootFolder = Project.RootFolder; 19 | Version = dir(fullfile(RootFolder,"public","TestResults*.txt")); 20 | Version = extractBetween([Version.name],"TestResults_",".txt"); 21 | end 22 | 23 | end 24 | 25 | methods (TestClassSetup) 26 | 27 | function SetUpSmokeTest(testCase,Project) 28 | try 29 | currentProject; 30 | catch 31 | error("Project is not loaded.") 32 | end 33 | end 34 | 35 | end 36 | 37 | methods(Test) 38 | 39 | function CheckResults(testCase,Version) 40 | File = fullfile("public","TestResults_"+Version+".txt"); 41 | Results = readtable(File,TextType="string"); 42 | if ~all(Results.Passed) 43 | error("Some of the tests did not pass.") 44 | end 45 | end 46 | 47 | end 48 | 49 | end -------------------------------------------------------------------------------- /SoftwareTests/FunctionTests.m: -------------------------------------------------------------------------------- 1 | classdef FunctionTests < matlab.unittest.TestCase 2 | 3 | properties (ClassSetupParameter) 4 | Project = {currentProject()}; 5 | end 6 | methods (TestClassSetup) 7 | 8 | function SetUpFunctionTest(testCase,Project) 9 | try 10 | currentProject; 11 | catch ME 12 | warning("Project is not loaded.") 13 | end 14 | end 15 | end % TestClassSetup 16 | 17 | methods(Test) 18 | 19 | function dataExists(testCase) 20 | load("hand2.mat","x","y") 21 | clear x y 22 | load("car.mat","xCar","yCar") 23 | clear xCar yCar 24 | load("drawing.mat","x","y") 25 | clear x y 26 | load("lakeData.mat","lakeX","lakeY","scale") 27 | clear lakeY lakeX scale 28 | load("modernLakeData.mat","latScale","longScale","modLakeLat","modLakeLong") 29 | clear latScale longScale modLakeLat modLakeLong 30 | load("myStorm.mat","myStorm") 31 | clear myStorm 32 | end 33 | 34 | end % methods 35 | 36 | end % classdef -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostHand.m: -------------------------------------------------------------------------------- 1 | % Post-run script for Hand.mlx 2 | % ---- Post-run commands ----- 3 | 4 | clear x y 5 | if exist(fullfile(currentProject().RootFolder,"Data","hand.mat"),"file") 6 | fp = fullfile(currentProject().RootFolder,"Data","hand.mat"); 7 | delete(fp) 8 | end -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostHandSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for HandSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | clear x y 5 | if exist(fullfile(currentProject().RootFolder,"Data","testDrawing.mat"),"file") 6 | fp = fullfile(currentProject().RootFolder,"Data","testDrawing.mat"); 7 | delete(fp) 8 | end 9 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostImplementExplicitSolver.m: -------------------------------------------------------------------------------- 1 | % Post-run script for ImplementExplicitSolver.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostImplementExplicitSolverSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for ImplementExplicitSolverSoln.mlx 2 | % ---- Post-run commands ----- 3 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostInterpolation.m: -------------------------------------------------------------------------------- 1 | % Post-run script for Interpolation.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostInterpolationSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for InterpolationSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostMeasureLakeArea.m: -------------------------------------------------------------------------------- 1 | % Post-run script for MeasureLakeArea.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostMeasureLakeAreaSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for MeasureLakeAreaSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostNumericalDerivatives.m: -------------------------------------------------------------------------------- 1 | % Post-run script for NumericalDerivatives.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostNumericalDerivativesSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for NumericalDerivativesSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostNumericalIntegration.m: -------------------------------------------------------------------------------- 1 | % Post-run script for NumericalIntegration.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostNumericalIntegrationSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for NumericalIntegrationSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostNumericalODEs.m: -------------------------------------------------------------------------------- 1 | % Post-run script for NumericalODEs.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostNumericalODEsSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for NumericalODEsSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostNumericalPDEs.m: -------------------------------------------------------------------------------- 1 | % Post-run script for NumericalPDEs.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostNumericalPDEsSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for NumericalPDEsSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostPendulumModels.m: -------------------------------------------------------------------------------- 1 | % Post-run script for PendulumModels.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostPendulumModelsSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for PendulumModelsSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostTrackStorms.m: -------------------------------------------------------------------------------- 1 | % Post-run script for TrackStorms.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostTrackStormsSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for TrackStormsSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostSmokeTest.m: -------------------------------------------------------------------------------- 1 | function PostSmokeTest(ShowReport) 2 | arguments 3 | ShowReport (1,1) logical = false; 4 | end 5 | 6 | import matlab.unittest.plugins.TestRunnerPlugin; 7 | 8 | % Create the runner: 9 | Runner = matlab.unittest.TestRunner.withTextOutput; 10 | 11 | % Create report folder: 12 | Folder = fullfile(currentProject().RootFolder,"public"); 13 | if ~isfolder(Folder) 14 | mkdir(Folder) 15 | end 16 | 17 | % Add HTML plugin: 18 | Plugin = matlab.unittest.plugins.TestReportPlugin.producingHTML(Folder,... 19 | "IncludingPassingDiagnostics",true,... 20 | "IncludingCommandWindowText",false,... 21 | "LoggingLevel",matlab.automation.Verbosity(1)); 22 | Runner.addPlugin(Plugin); 23 | 24 | 25 | % Create Test Suite 26 | Suite = testsuite("CheckTestResults"); 27 | 28 | % Run the test suite 29 | Results = Runner.run(Suite); 30 | 31 | 32 | % Format the results in a table and save them 33 | Results = table(Results'); 34 | Version = extractBetween(string(Results.Name),"Version=",")"); 35 | Passed = Results.Passed; 36 | 37 | % Add link to other report 38 | File = fileread(fullfile("public","index.html")); 39 | for iVer = 1:length(Version) 40 | File = replace(File,"Version="+Version(iVer),... 41 | sprintf('%s',Version(iVer),"Version="+Version(iVer))); 42 | end 43 | writelines(File,fullfile("public","index.html"),"WriteMode","overwrite"); 44 | 45 | % Format the JSON file 46 | Badge = struct; 47 | Badge.schemaVersion = 1; 48 | Badge.label = "Test Status"; 49 | if all(Passed) 50 | Badge.color = "success"; 51 | Badge.message = join("R"+Version," | "); 52 | elseif any(Passed) 53 | Badge.color = "yellowgreen"; 54 | Badge.message = join("R") 55 | elseif all(~Passed) 56 | Badge.color = "critical"; 57 | Badge.message = join("R"+Version," | "); 58 | end 59 | Badge = jsonencode(Badge); 60 | writelines(Badge,fullfile("Images","TestedWith.json")); 61 | 62 | if ShowReport 63 | web(fullfile(Folder,"index.html")) 64 | end 65 | 66 | end -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreHand.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for Hand.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | CollectData = @()NewCollectData(); 7 | 8 | function varargout = NewCollectData() 9 | load("drawing.mat","x","y") 10 | varargout = {x,y} 11 | end -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreHandSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for HandSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreImplementExplicitSolver.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for ImplementExplicitSolver.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = "MATLAB:badsubscript"; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreImplementExplicitSolverSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for ImplementExplicitSolverSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | addpath(fullfile(currentProject().RootFolder,"InstructorResources","Solutions","FunctionLibrarySolutions")) 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreInterpolation.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for Interpolation.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreInterpolationSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for InterpolationSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | addpath(fullfile(currentProject().RootFolder,"InstructorResources","Solutions","FunctionLibrarySolutions")) 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreMeasureLakeArea.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for MeasureLakeArea.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | load lakeData.mat lakeX lakeY 7 | [~,idx] = max(diff(lakeX)); 8 | x = lakeX([idx:end 1:idx-1]); 9 | y = lakeY([idx:end 1:idx-1]); 10 | p.Position = [x y]; 11 | drawpolygon = p; 12 | openfig = @(in)figure; -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreMeasureLakeAreaSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for MeasureLakeAreaSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | load myLakeData.mat lakeX lakeY 6 | [~,idx] = max(diff(lakeX)); 7 | x = lakeX([idx:end 1:idx-1]); 8 | y = lakeY([idx:end 1:idx-1]); 9 | p.Position = [x y]; 10 | drawpolygon = p; 11 | openfig = @(in)figure; 12 | 13 | IdentifyLakeShape = @()LoadModernData(); 14 | MeasureGeoScale = @()LoadGeoScale(); 15 | 16 | function roi = LoadModernData 17 | load myModernLakeData.mat modLakeLat modLakeLong 18 | out.Position = [modLakeLat modLakeLong]; 19 | roi=out; 20 | end 21 | 22 | function longScale = LoadGeoScale() 23 | load myModernLakeData.mat longScale 24 | end -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreNumericalDerivatives.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for NumericalDerivatives.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreNumericalDerivativesSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for NumericalDerivativesSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreNumericalIntegration.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for NumericalIntegration.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreNumericalIntegrationSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for NumericalIntegrationSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | addpath(fullfile(currentProject().RootFolder,"InstructorResources","Solutions","FunctionLibrarySolutions")) 6 | 7 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreNumericalODEs.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for NumericalODEs.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreNumericalODEsSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for NumericalODEsSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | addpath(fullfile(currentProject().RootFolder,"InstructorResources","Solutions","FunctionLibrarySolutions")) 7 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreNumericalPDEs.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for NumericalPDEs.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreNumericalPDEsSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for NumericalPDEsSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | addpath(fullfile(currentProject().RootFolder,"InstructorResources","Solutions","FunctionLibrarySolutions")) 7 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PrePendulumModels.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for PendulumModels.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = "MATLAB:unassignedOutputs"; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PrePendulumModelsSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for PendulumModelsSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreTrackStorms.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for TrackStorms.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreTrackStormsSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for TrackStormsSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/RunAllTests.m: -------------------------------------------------------------------------------- 1 | function RunAllTests(ShowReport) 2 | arguments 3 | ShowReport (1,1) logical = false; 4 | end 5 | 6 | import matlab.unittest.plugins.TestReportPlugin; 7 | 8 | % Create a runner 9 | Runner = matlab.unittest.TestRunner.withTextOutput; 10 | Folder = fullfile(currentProject().RootFolder,"public",version("-release")); 11 | if ~isfolder(Folder) 12 | mkdir(Folder) 13 | else 14 | rmdir(Folder,'s') 15 | mkdir(Folder) 16 | end 17 | Plugin = TestReportPlugin.producingHTML(Folder,... 18 | "IncludingPassingDiagnostics",true,... 19 | "IncludingCommandWindowText",true,... 20 | "LoggingLevel",matlab.automation.Verbosity(1)); 21 | Runner.addPlugin(Plugin); 22 | 23 | 24 | % Create the test suite with SmokeTest and Function test if they exist 25 | Suite = testsuite("SmokeTests"); 26 | Suite = [Suite testsuite("FunctionTests")]; 27 | Suite = [Suite testsuite("SolnSmokeTests")]; 28 | 29 | % Run the test suite 30 | Results = Runner.run(Suite); 31 | 32 | if ShowReport 33 | web(fullfile(Folder,"index.html")) 34 | end 35 | 36 | % Format the results in a table and save them 37 | ResultsTable = table(Results') 38 | writetable(ResultsTable,fullfile(currentProject().RootFolder,... 39 | "public","TestResults_"+version("-release")+".txt")); 40 | 41 | % Assert success of test 42 | assertSuccess(Results); 43 | 44 | end 45 | -------------------------------------------------------------------------------- /SoftwareTests/SmokeTests.m: -------------------------------------------------------------------------------- 1 | classdef SmokeTests < matlab.unittest.TestCase 2 | 3 | properties 4 | RootFolder 5 | sparedEditors % Files already open when the test starts 6 | end % properties 7 | 8 | properties (ClassSetupParameter) 9 | Project = {currentProject()}; 10 | end % ClassSetupParameter 11 | 12 | properties (TestParameter) 13 | File; 14 | end % TestParameter 15 | 16 | methods (TestParameterDefinition,Static) 17 | 18 | function File = RetrieveFile(Project) %#ok 19 | % Retrieve student template files: 20 | RootFolder = currentProject().RootFolder; 21 | File = dir(fullfile(RootFolder,"Scripts","*.mlx")); 22 | File = {File.name}; 23 | end 24 | 25 | end % Static TestParameterDefinition 26 | 27 | methods (TestClassSetup) 28 | 29 | function SetUpSmokeTest(testCase,Project) %#ok 30 | % Navigate to project root folder: 31 | testCase.RootFolder = Project.RootFolder; 32 | cd(testCase.RootFolder) 33 | 34 | % Close the StartUp app if still open: 35 | delete(findall(groot,'Name','StartUp App')) 36 | 37 | % Log MATLAB version: 38 | testCase.log("Running in " + version) 39 | end 40 | 41 | end % TestClassSetup 42 | 43 | methods(TestMethodSetup) 44 | function recordEditorsToSpare(testCase) 45 | testCase.sparedEditors = matlab.desktop.editor.getAll; 46 | testCase.sparedEditors = {testCase.sparedEditors.Filename}; 47 | end 48 | end % TestMethodSetup 49 | 50 | methods(TestMethodTeardown) 51 | function closeOpenedEditors_thenDeleteWorkingDir(testCase) 52 | openEditors = matlab.desktop.editor.getAll; 53 | for editor=openEditors(1:end) 54 | if any(strcmp(editor.Filename, testCase.sparedEditors)) 55 | continue; 56 | end 57 | % if not on our list, close the file 58 | editor.close(); 59 | end 60 | end 61 | end % TestMethodTeardown 62 | 63 | methods(Test) 64 | 65 | function SmokeRun(testCase,File) 66 | 67 | % Navigate to project root folder: 68 | cd(testCase.RootFolder) 69 | FileToRun = string(File); 70 | 71 | % Pre-test: 72 | PreFiles = CheckPreFile(testCase,FileToRun); 73 | run(PreFiles); 74 | 75 | % Run SmokeTest 76 | disp(">> Running " + FileToRun); 77 | try 78 | run(fullfile("Scripts",FileToRun)); 79 | catch ME 80 | 81 | end 82 | 83 | % Post-test: 84 | PostFiles = CheckPostFile(testCase,FileToRun); 85 | run(PostFiles) 86 | 87 | % Log every figure created during run: 88 | Figures = findall(groot,'Type','figure'); 89 | Figures = flipud(Figures); 90 | if ~isempty(Figures) 91 | for f = 1:size(Figures,1) 92 | if ~isempty(Figures(f).Number) 93 | FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f),'Formats','png'); 94 | log(testCase,1,FigDiag); 95 | end 96 | end 97 | end 98 | 99 | % Close all figures and Simulink models 100 | close all force 101 | if any(matlab.addons.installedAddons().Name == "Simulink") 102 | bdclose all 103 | end 104 | 105 | % Rethrow error if any 106 | if exist("ME","var") 107 | if ~any(strcmp(ME.identifier,KnownIssuesID)) 108 | rethrow(ME) 109 | end 110 | end 111 | 112 | end 113 | 114 | end % Test Methods 115 | 116 | 117 | methods (Access = private) 118 | 119 | function Path = CheckPreFile(testCase,Filename) 120 | PreFile = "Pre"+replace(Filename,".mlx",".m"); 121 | PreFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PreFiles",PreFile); 122 | if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles")) 123 | mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles")) 124 | end 125 | if ~isfile(PreFilePath) 126 | writelines("% Pre-run script for "+Filename,PreFilePath) 127 | writelines("% ---- Known Issues -----",PreFilePath,'WriteMode','append'); 128 | writelines("KnownIssuesID = "+char(34)+char(34)+";",PreFilePath,'WriteMode','append'); 129 | writelines("% ---- Pre-run commands -----",PreFilePath,'WriteMode','append'); 130 | writelines(" ",PreFilePath,'WriteMode','append'); 131 | end 132 | Path = PreFilePath; 133 | end 134 | 135 | function Path = CheckPostFile(testCase,Filename) 136 | PostFile = "Post"+replace(Filename,".mlx",".m"); 137 | PostFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PostFiles",PostFile); 138 | if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles")) 139 | mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles")) 140 | end 141 | if ~isfile(PostFilePath) 142 | writelines("% Post-run script for "+Filename,PostFilePath) 143 | writelines("% ---- Post-run commands -----",PostFilePath,'WriteMode','append'); 144 | writelines(" ",PostFilePath,'WriteMode','append'); 145 | end 146 | Path = PostFilePath; 147 | end 148 | 149 | end % Private Methods 150 | 151 | end % Smoketests -------------------------------------------------------------------------------- /SoftwareTests/SolnSmokeTests.m: -------------------------------------------------------------------------------- 1 | classdef SolnSmokeTests < matlab.unittest.TestCase 2 | 3 | properties 4 | RootFolder 5 | isSolnOnPath 6 | sparedEditors % Track open files 7 | end % properties 8 | 9 | properties (ClassSetupParameter) 10 | Project = {currentProject()}; 11 | end % ClassSetupParameter 12 | 13 | methods(TestMethodSetup) 14 | function recordEditorsToSpare(testCase) 15 | testCase.sparedEditors = matlab.desktop.editor.getAll; 16 | testCase.sparedEditors = {testCase.sparedEditors.Filename}; 17 | end 18 | end % TestMethodSetup 19 | 20 | methods(TestMethodTeardown) 21 | function closeOpenedEditors_thenDeleteWorkingDir(testCase) 22 | openEditors = matlab.desktop.editor.getAll; 23 | for editor=openEditors(1:end) 24 | if any(strcmp(editor.Filename, testCase.sparedEditors)) 25 | continue; 26 | end 27 | % if not on our list, close the file 28 | editor.close(); 29 | end 30 | end 31 | end % TestMethodTeardown 32 | 33 | properties (TestParameter) 34 | File; 35 | end % TestParameter 36 | 37 | methods (TestParameterDefinition,Static) 38 | 39 | function File = GetScriptName(Project) 40 | % Retrieve student template files: 41 | RootFolder = Project.RootFolder; 42 | File = dir(fullfile(RootFolder,"Scripts","*.mlx")); 43 | File = {File.name}; 44 | end 45 | 46 | end % Static TestParameterDefinition 47 | 48 | methods (TestClassSetup) 49 | 50 | function SetUpPath(testCase,Project) 51 | % Navigate to project root folder: 52 | testCase.RootFolder = Project.RootFolder; 53 | cd(testCase.RootFolder) 54 | 55 | % Check that solutions are on path: 56 | testCase.isSolnOnPath = isfolder("Solutions"); 57 | if testCase.isSolnOnPath == 0 58 | addpath(fullfile(testCase.RootFolder,"InstructorResources","Solutions")) 59 | end 60 | 61 | % Close the StartUp app if still open: 62 | delete(findall(groot,'Name','StartUp App')) 63 | 64 | % Log MATLAB version: 65 | testCase.log("Running in " + version) 66 | 67 | end % function setUpPath 68 | 69 | end % methods (TestClassSetup) 70 | 71 | methods(Test) 72 | 73 | % Check that solutions files exist for each of the student 74 | % templates 75 | function ExistSolns(testCase,File) 76 | SolutionName = replace(string(File),".mlx","Soln.mlx"); 77 | assert(exist(SolutionName,"file"),"Missing solutions for "+File); 78 | end 79 | 80 | 81 | function SmokeRun(testCase,File) 82 | 83 | % Navigate to project root folder: 84 | cd(testCase.RootFolder) 85 | FileToRun = replace(string(File),".mlx","Soln.mlx"); 86 | 87 | % Pre-test: 88 | PreFiles = CheckPreFile(testCase,FileToRun); 89 | run(PreFiles); 90 | 91 | % Run SmokeTest 92 | disp(">> Running " + FileToRun); 93 | try 94 | run(fullfile("InstructorResources","Solutions",FileToRun)); 95 | catch ME 96 | 97 | end 98 | 99 | % Post-test: 100 | PostFiles = CheckPostFile(testCase,FileToRun); 101 | run(PostFiles) 102 | 103 | % Log every figure created during run: 104 | Figures = findall(groot,'Type','figure'); 105 | Figures = flipud(Figures); 106 | if ~isempty(Figures) 107 | for f = 1:size(Figures,1) 108 | if ~isempty(Figures(f).Number) 109 | FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f),'Formats','png'); 110 | log(testCase,1,FigDiag); 111 | end 112 | end 113 | end 114 | 115 | % Close all figures and Simulink models 116 | close all force 117 | if any(matlab.addons.installedAddons().Name == "Simulink") 118 | bdclose all 119 | end 120 | 121 | % Rethrow error if any 122 | if exist("ME","var") 123 | if ~any(strcmp(ME.identifier,KnownIssuesID)) 124 | rethrow(ME) 125 | end 126 | end 127 | 128 | end 129 | 130 | end % Test Methods 131 | 132 | methods (Access = private) 133 | 134 | function Path = CheckPreFile(testCase,Filename) 135 | PreFile = "Pre"+replace(Filename,".mlx",".m"); 136 | PreFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PreFiles",PreFile); 137 | if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles")) 138 | mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles")) 139 | end 140 | if ~isfile(PreFilePath) 141 | writelines("% Pre-run script for "+Filename,PreFilePath) 142 | writelines("% ---- Known Issues -----",PreFilePath,'WriteMode','append'); 143 | writelines("KnownIssuesID = "+char(34)+char(34)+";",PreFilePath,'WriteMode','append'); 144 | writelines("% ---- Pre-run commands -----",PreFilePath,'WriteMode','append'); 145 | writelines(" ",PreFilePath,'WriteMode','append'); 146 | end 147 | Path = PreFilePath; 148 | end 149 | 150 | function Path = CheckPostFile(testCase,Filename) 151 | PostFile = "Post"+replace(Filename,".mlx",".m"); 152 | PostFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PostFiles",PostFile); 153 | if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles")) 154 | mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles")) 155 | end 156 | if ~isfile(PostFilePath) 157 | writelines("% Post-run script for "+Filename,PostFilePath) 158 | writelines("% ---- Post-run commands -----",PostFilePath,'WriteMode','append'); 159 | writelines(" ",PostFilePath,'WriteMode','append'); 160 | end 161 | Path = PostFilePath; 162 | end 163 | 164 | end % Private Access Methods 165 | 166 | end % SolnSmokeTests 167 | -------------------------------------------------------------------------------- /SoftwareTests/TestResults_R2024a.txt: -------------------------------------------------------------------------------- 1 | Name,Passed,Failed,Incomplete,Duration,Details 2 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=Hand.mlx),1,0,0,0.0081279, 3 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=ImplementExplicitSolver.mlx),1,0,0,3.4182225, 4 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=Interpolation.mlx),1,0,0,27.383437, 5 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=MeasureLakeArea.mlx),1,0,0,38.1402992, 6 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=NumericalDerivatives.mlx),1,0,0,5.7204374, 7 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=NumericalIntegration.mlx),1,0,0,11.6439181, 8 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=NumericalODEs.mlx),1,0,0,9.5377586, 9 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=NumericalPDEs.mlx),1,0,0,57.0697041, 10 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=PendulumModels.mlx),1,0,0,3.8335752, 11 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=TrackStorms.mlx),1,0,0,157.3072403, 12 | FunctionTests[Project=0x0_char]/dataExists,1,0,0,0.0229859, 13 | -------------------------------------------------------------------------------- /SoftwareTests/TestResults_R2024b.txt: -------------------------------------------------------------------------------- 1 | Name,Passed,Failed,Incomplete,Duration,Details 2 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=Hand.mlx),1,0,0,1.0933756, 3 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=ImplementExplicitSolver.mlx),1,0,0,0.0002897, 4 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=Interpolation.mlx),1,0,0,0.0004386, 5 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=MeasureLakeArea.mlx),1,0,0,26.1523377, 6 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=NumericalDerivatives.mlx),1,0,0,0.0012912, 7 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=NumericalIntegration.mlx),1,0,0,1.72e-05, 8 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=NumericalODEs.mlx),1,0,0,9.6e-06, 9 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=NumericalPDEs.mlx),1,0,0,7.9e-06, 10 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=PendulumModels.mlx),1,0,0,0.0001478, 11 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=TrackStorms.mlx),1,0,0,0.3293405, 12 | FunctionTests[Project=0x0_char]/dataExists,1,0,0,0.0193367, 13 | -------------------------------------------------------------------------------- /SoftwareTests/myLakeData.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Numerical-Methods-with-Applications/5e673a15084812441c6834cf4e0d95c3dd3407fe/SoftwareTests/myLakeData.mat -------------------------------------------------------------------------------- /Utilities/ProjectShutdown.m: -------------------------------------------------------------------------------- 1 | % Close the StartUp app if still open: 2 | delete(findall(groot,'Name','StartUp App')) -------------------------------------------------------------------------------- /Utilities/ProjectStartupApp.m: -------------------------------------------------------------------------------- 1 | classdef ProjectStartupApp < matlab.apps.AppBase 2 | 3 | % Properties that correspond to app components 4 | properties (Access = public) 5 | StartUpAppUIFigure matlab.ui.Figure 6 | TabGroup matlab.ui.container.TabGroup 7 | WelcomeTab matlab.ui.container.Tab 8 | Image matlab.ui.control.Image 9 | READMEButton matlab.ui.control.Button 10 | ReviewUsButton matlab.ui.control.Button 11 | MainMenuButton matlab.ui.control.Button 12 | WelcomeTitle matlab.ui.control.Label 13 | TabReview matlab.ui.container.Tab 14 | OtherButton matlab.ui.control.Button 15 | StudentButton matlab.ui.control.Button 16 | FacultyButton matlab.ui.control.Button 17 | Q1 matlab.ui.control.Label 18 | ReviewTitle matlab.ui.control.Label 19 | ReviewText matlab.ui.control.Label 20 | end 21 | 22 | 23 | properties (Access = private) 24 | GitHubOrganization = "MathWorks-Teaching-Resources"; % Description 25 | GitHubRepository = "Numerical-Methods-with-Applications"; 26 | end 27 | %% How to customize the app? 28 | %{ 29 | 30 | This StartUp app is designed to be customized to your module. It 31 | requires a minimum number of customization: 32 | 33 | 1. Change "Module Template" in app.WelcomeTitle by your module name 34 | 2. Change "Module Template" in app.ReviewTitle by your module name 35 | 3. Change the GitHubRepository (line 25) to the correct value 36 | 4. Change image in app.Image by the cover image you would like for your 37 | module. This image should be located in rootFolder/Images 38 | 5. Create your MS Form: 39 | a. Make a copy of the Faculty and the Student Template surveys 40 | b. Customize the name of the survey to match the name of your 41 | survey 42 | c. Click on "Collect responses", select "Anyone can respond" and 43 | copy the form link to SetupAppLinks (see step 6). 44 | 5. Create your MS Sway: 45 | a. Go to MS Sway 46 | b. Create a blank sway 47 | c. Add the name of your module to the title box 48 | d. Click "Share", Select "Anyone with a link", Select "View" 49 | e. Copy the sway link to SetupAppLinks (see step 6). 50 | 6. Add the Survey and Sway link to Utilities/SurveyLinks using 51 | SetupAppLinks.mlx in InternalFiles/RequiredFunctions/StartUpFcn 52 | 7. Save > Export to .m file and save the result as 53 | Utilities/ProjectStartupApp.m 54 | 55 | %} 56 | 57 | methods (Access = private, Static) 58 | 59 | function pingSway(app) 60 | try 61 | if ~ispref("MCCTEAM") 62 | load Utilities\SurveyLinks.mat SwayLink 63 | webread(SwayLink); 64 | end 65 | catch 66 | end 67 | end 68 | 69 | function openStudentForm(app) 70 | try 71 | load Utilities\SurveyLinks.mat StudentFormLink 72 | web(StudentFormLink); 73 | catch 74 | end 75 | end 76 | 77 | function openFacultyForm(app) 78 | try 79 | load Utilities\SurveyLinks.mat FacultyFormLink 80 | web(FacultyFormLink); 81 | catch 82 | end 83 | end 84 | 85 | function saveSettings(isReviewed,numLoad) 86 | try 87 | save(fullfile("Utilities","ProjectSettings.mat"),"isReviewed","numLoad"); 88 | catch 89 | end 90 | end 91 | 92 | end 93 | 94 | 95 | % Callbacks that handle component events 96 | methods (Access = private) 97 | 98 | % Code that executes after component creation 99 | function startupFcn(app) 100 | 101 | % Switch tab to review if has not been reviewed yet 102 | if isfile(fullfile("Utilities","ProjectSettings.mat")) 103 | load(fullfile("Utilities","ProjectSettings.mat"),"isReviewed","numLoad"); 104 | numLoad = numLoad + 1; % Increment counter 105 | else 106 | isReviewed = false; 107 | numLoad = 1; % Initialize counter 108 | end 109 | 110 | % Switch tab for review 111 | if ~isReviewed && numLoad > 2 112 | isReviewed = true; 113 | app.TabGroup.SelectedTab = app.TabReview; 114 | end 115 | 116 | % Save new settings 117 | app.saveSettings(isReviewed,numLoad) 118 | 119 | % Download links to survey (should only work when module goes 120 | % public on GitHub) 121 | try 122 | import matlab.net.* 123 | import matlab.net.http.* 124 | 125 | Request = RequestMessage; 126 | Request.Method = 'GET'; 127 | Address = URI("http://api.github.com/repos/"+app.GitHubOrganization+... 128 | "/"+app.GitHubRepository+"/contents/Utilities/SurveyLinks.mat"); 129 | Request.Header = HeaderField("X-GitHub-Api-Version","2022-11-28"); 130 | Request.Header(2) = HeaderField("Accept","application/vnd.github+json"); 131 | [Answer,~,~] = send(Request,Address); 132 | websave(fullfile("Utilities/SurveyLinks.mat"),Answer.Body.Data.download_url); 133 | catch 134 | end 135 | 136 | end 137 | 138 | % Close request function: StartUpAppUIFigure 139 | function StartUpAppUIFigureCloseRequest(app, event) 140 | if event.Source == app.READMEButton 141 | open README.mlx 142 | elseif event.Source == app.MainMenuButton 143 | open MainMenu.mlx 144 | elseif event.Source == app.FacultyButton 145 | open MainMenu.mlx 146 | elseif event.Source == app.StudentButton 147 | open MainMenu.mlx 148 | elseif event.Source == app.OtherButton 149 | open MainMenu.mlx 150 | else 151 | disp("Thank you for your time.") 152 | end 153 | delete(app) 154 | end 155 | 156 | % Button pushed function: MainMenuButton 157 | function MainMenuButtonPushed(app, event) 158 | StartUpAppUIFigureCloseRequest(app,event) 159 | end 160 | 161 | % Button pushed function: FacultyButton 162 | function FacultyButtonPushed(app, event) 163 | app.pingSway; 164 | app.openFacultyForm; 165 | StartUpAppUIFigureCloseRequest(app,event) 166 | end 167 | 168 | % Button pushed function: StudentButton 169 | function StudentButtonPushed(app, event) 170 | app.pingSway; 171 | app.openStudentForm; 172 | StartUpAppUIFigureCloseRequest(app,event) 173 | end 174 | 175 | % Button pushed function: OtherButton 176 | function OtherButtonPushed(app, event) 177 | app.pingSway; 178 | app.openStudentForm; 179 | StartUpAppUIFigureCloseRequest(app,event) 180 | end 181 | 182 | % Button pushed function: ReviewUsButton 183 | function ReviewUsButtonPushed(app, event) 184 | app.TabGroup.SelectedTab = app.TabReview; 185 | end 186 | 187 | % Button pushed function: READMEButton 188 | function READMEButtonPushed(app, event) 189 | StartUpAppUIFigureCloseRequest(app,event) 190 | end 191 | end 192 | 193 | % Component initialization 194 | methods (Access = private) 195 | 196 | % Create UIFigure and components 197 | function createComponents(app) 198 | 199 | % Create StartUpAppUIFigure and hide until all components are created 200 | app.StartUpAppUIFigure = uifigure('Visible', 'off'); 201 | app.StartUpAppUIFigure.AutoResizeChildren = 'off'; 202 | app.StartUpAppUIFigure.Position = [100 100 276 430]; 203 | app.StartUpAppUIFigure.Name = 'StartUp App'; 204 | app.StartUpAppUIFigure.Resize = 'off'; 205 | app.StartUpAppUIFigure.CloseRequestFcn = createCallbackFcn(app, @StartUpAppUIFigureCloseRequest, true); 206 | 207 | % Create TabGroup 208 | app.TabGroup = uitabgroup(app.StartUpAppUIFigure); 209 | app.TabGroup.AutoResizeChildren = 'off'; 210 | app.TabGroup.Position = [1 1 276 460]; 211 | 212 | % Create WelcomeTab 213 | app.WelcomeTab = uitab(app.TabGroup); 214 | app.WelcomeTab.AutoResizeChildren = 'off'; 215 | app.WelcomeTab.Title = 'Tab'; 216 | 217 | % Create WelcomeTitle 218 | app.WelcomeTitle = uilabel(app.WelcomeTab); 219 | app.WelcomeTitle.HorizontalAlignment = 'center'; 220 | app.WelcomeTitle.VerticalAlignment = 'top'; 221 | app.WelcomeTitle.WordWrap = 'on'; 222 | app.WelcomeTitle.FontSize = 24; 223 | app.WelcomeTitle.FontWeight = 'bold'; 224 | app.WelcomeTitle.Position = [2 349 274 70]; 225 | app.WelcomeTitle.Text = 'Numerical Methods with Applications'; 226 | 227 | % Create MainMenuButton 228 | app.MainMenuButton = uibutton(app.WelcomeTab, 'push'); 229 | app.MainMenuButton.ButtonPushedFcn = createCallbackFcn(app, @MainMenuButtonPushed, true); 230 | app.MainMenuButton.FontSize = 18; 231 | app.MainMenuButton.Position = [59 96 161 35]; 232 | app.MainMenuButton.Text = 'Main Menu'; 233 | 234 | % Create ReviewUsButton 235 | app.ReviewUsButton = uibutton(app.WelcomeTab, 'push'); 236 | app.ReviewUsButton.ButtonPushedFcn = createCallbackFcn(app, @ReviewUsButtonPushed, true); 237 | app.ReviewUsButton.FontSize = 18; 238 | app.ReviewUsButton.Position = [59 10 161 35]; 239 | app.ReviewUsButton.Text = 'Review Us'; 240 | 241 | % Create READMEButton 242 | app.READMEButton = uibutton(app.WelcomeTab, 'push'); 243 | app.READMEButton.ButtonPushedFcn = createCallbackFcn(app, @READMEButtonPushed, true); 244 | app.READMEButton.FontSize = 18; 245 | app.READMEButton.Position = [59 53 161 35]; 246 | app.READMEButton.Text = 'README'; 247 | 248 | % Create Image 249 | app.Image = uiimage(app.WelcomeTab); 250 | app.Image.Position = [16 141 245 209]; 251 | app.Image.ImageSource = 'BakerLakeSR.png'; 252 | 253 | % Create TabReview 254 | app.TabReview = uitab(app.TabGroup); 255 | app.TabReview.AutoResizeChildren = 'off'; 256 | app.TabReview.Title = 'Tab2'; 257 | app.TabReview.HandleVisibility = 'off'; 258 | 259 | % Create ReviewText 260 | app.ReviewText = uilabel(app.TabReview); 261 | app.ReviewText.HorizontalAlignment = 'center'; 262 | app.ReviewText.VerticalAlignment = 'top'; 263 | app.ReviewText.WordWrap = 'on'; 264 | app.ReviewText.FontSize = 18; 265 | app.ReviewText.Position = [16 243 245 69]; 266 | app.ReviewText.Text = 'Please help us improve your experience by answering a few questions.'; 267 | 268 | % Create ReviewTitle 269 | app.ReviewTitle = uilabel(app.TabReview); 270 | app.ReviewTitle.HorizontalAlignment = 'center'; 271 | app.ReviewTitle.VerticalAlignment = 'top'; 272 | app.ReviewTitle.WordWrap = 'on'; 273 | app.ReviewTitle.FontSize = 24; 274 | app.ReviewTitle.FontWeight = 'bold'; 275 | app.ReviewTitle.Position = [2 326 274 93]; 276 | app.ReviewTitle.Text = 'Numerical Methods with Applications'; 277 | 278 | % Create Q1 279 | app.Q1 = uilabel(app.TabReview); 280 | app.Q1.HorizontalAlignment = 'center'; 281 | app.Q1.VerticalAlignment = 'top'; 282 | app.Q1.WordWrap = 'on'; 283 | app.Q1.FontSize = 18; 284 | app.Q1.FontWeight = 'bold'; 285 | app.Q1.Position = [16 141 245 69]; 286 | app.Q1.Text = 'What describes you best?'; 287 | 288 | % Create FacultyButton 289 | app.FacultyButton = uibutton(app.TabReview, 'push'); 290 | app.FacultyButton.ButtonPushedFcn = createCallbackFcn(app, @FacultyButtonPushed, true); 291 | app.FacultyButton.FontSize = 18; 292 | app.FacultyButton.Position = [64 127 150 40]; 293 | app.FacultyButton.Text = 'Faculty'; 294 | 295 | % Create StudentButton 296 | app.StudentButton = uibutton(app.TabReview, 'push'); 297 | app.StudentButton.ButtonPushedFcn = createCallbackFcn(app, @StudentButtonPushed, true); 298 | app.StudentButton.FontSize = 18; 299 | app.StudentButton.Position = [64 80 150 40]; 300 | app.StudentButton.Text = 'Student'; 301 | 302 | % Create OtherButton 303 | app.OtherButton = uibutton(app.TabReview, 'push'); 304 | app.OtherButton.ButtonPushedFcn = createCallbackFcn(app, @OtherButtonPushed, true); 305 | app.OtherButton.FontSize = 18; 306 | app.OtherButton.Position = [64 34 150 40]; 307 | app.OtherButton.Text = 'Other'; 308 | 309 | % Show the figure after all components are created 310 | app.StartUpAppUIFigure.Visible = 'on'; 311 | end 312 | end 313 | 314 | % App creation and deletion 315 | methods (Access = public) 316 | 317 | % Construct app 318 | function app = ProjectStartupApp 319 | 320 | % Create UIFigure and components 321 | createComponents(app) 322 | 323 | % Register the app with App Designer 324 | registerApp(app, app.StartUpAppUIFigure) 325 | 326 | % Execute the startup function 327 | runStartupFcn(app, @startupFcn) 328 | 329 | if nargout == 0 330 | clear app 331 | end 332 | end 333 | 334 | % Code that executes before app deletion 335 | function delete(app) 336 | 337 | % Delete UIFigure when app is deleted 338 | delete(app.StartUpAppUIFigure) 339 | end 340 | end 341 | end -------------------------------------------------------------------------------- /resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/2R0-o249XdrxUDxChRL1MrtyIeEd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/2R0-o249XdrxUDxChRL1MrtyIeEp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/ApixlSTDAdp3GgxzMHKu0Fhfr6Id.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/ApixlSTDAdp3GgxzMHKu0Fhfr6Ip.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/P0dCXqU2TY1GykJweoJ37itMc78d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/P0dCXqU2TY1GykJweoJ37itMc78p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/Qg7ozviHBAR9M3EKyM28wXK7XCQd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/Qg7ozviHBAR9M3EKyM28wXK7XCQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/S2_lG2GXW82QbxegJJWd7IrKtlwd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/S2_lG2GXW82QbxegJJWd7IrKtlwp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/Xjlo1m2A3FCGrq601wagkpx_ycsd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/Xjlo1m2A3FCGrq601wagkpx_ycsp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/YH64LtKYtQhOo-dosLLP8CBfX3kd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/YH64LtKYtQhOo-dosLLP8CBfX3kp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/cG8QwElnYEQuaCWyUvA9YF124v8d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/cG8QwElnYEQuaCWyUvA9YF124v8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/tDhuEtF2_L7Vzt3RGzNsc_A3TRYd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/tDhuEtF2_L7Vzt3RGzNsc_A3TRYp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/wCdpXJngLvCgG-kPbX2z7g_ijRYd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/wCdpXJngLvCgG-kPbX2z7g_ijRYp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/yvc00et_D9w1RZcV5T2-bniDUu0d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/8h3kimKoV3g5SPdcFPq6bNqde20/yvc00et_D9w1RZcV5T2-bniDUu0p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/4JuqxfFjWu6twt8CqM4nt7feqakd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/4JuqxfFjWu6twt8CqM4nt7feqakp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/7-1B9IYtiDSgVt8bX4miP7Ae2qkd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/7-1B9IYtiDSgVt8bX4miP7Ae2qkp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/Dc59WDtag_rG4XkTmXZI8D-rEHQd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/Dc59WDtag_rG4XkTmXZI8D-rEHQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/P1l14w_H1m1DxTKzPmPMl1YHOhEd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/P1l14w_H1m1DxTKzPmPMl1YHOhEp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/Ur1esh7xN9L6aqDUKBE31DKE1Qod.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/Ur1esh7xN9L6aqDUKBE31DKE1Qop.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/Y4Dbs1ki764_FbTDx4JqKWeLH2cd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/Y4Dbs1ki764_FbTDx4JqKWeLH2cp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/cun28KIqfMV5dplLoh1WqjdCS8cd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/cun28KIqfMV5dplLoh1WqjdCS8cp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/nzB5D5dN-y0P0MZ52QkerA1i0Q4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/nzB5D5dN-y0P0MZ52QkerA1i0Q4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/vWXe0RyZPdhHUw9cHcgocR1TaiAd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/vWXe0RyZPdhHUw9cHcgocR1TaiAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/wqJGEIaUV60vBsQBPjBwhhEPdzod.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/wqJGEIaUV60vBsQBPjBwhhEPdzop.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/xJol_hmopCm1uPehMxgeZG8rtcsd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/xJol_hmopCm1uPehMxgeZG8rtcsp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BjxNC43HIPP8KZwg_cceb68ikkA/dxW0rLxFMXm0cpQGCSkWQRi2YRsd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BjxNC43HIPP8KZwg_cceb68ikkA/dxW0rLxFMXm0cpQGCSkWQRi2YRsp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dNSwd3FTbBY0j-vjD3y6Lzhg5WQd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dNSwd3FTbBY0j-vjD3y6Lzhg5WQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e1K2asjf1AG8_lJdlO0WXpNP2YQd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e1K2asjf1AG8_lJdlO0WXpNP2YQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/jSqfwSDlRVqL_9fEXfOnybDRVxod.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/jSqfwSDlRVqL_9fEXfOnybDRVxop.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/x9kRh-n1S7s6yE1EzN4stHJjWq0d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/x9kRh-n1S7s6yE1EzN4stHJjWq0p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/HoHDHQ_WvHAAKj5aJOrvrg_vpt8/xXlmKuOQ7YT_G1elNhbKQIUqSRMd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/HoHDHQ_WvHAAKj5aJOrvrg_vpt8/xXlmKuOQ7YT_G1elNhbKQIUqSRMp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/xcK8fO1pjra5DR0jot5vrzlBV84d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/xcK8fO1pjra5DR0jot5vrzlBV84p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/y8P_Fq2qJ6We-JIH8JyFmcTdT2wd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/y8P_Fq2qJ6We-JIH8JyFmcTdT2wp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/2kj09UetkV_lru3gvSPXnY6-nM4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/2kj09UetkV_lru3gvSPXnY6-nM4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/KKyDJtbdIBOlaeHmIZd5VX6vqx8d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/KKyDJtbdIBOlaeHmIZd5VX6vqx8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/QWNDYJD5mGW1bWYvPx9DtKnxzw4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/QWNDYJD5mGW1bWYvPx9DtKnxzw4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/R1RggVhA72agIvELiuhWPRS8F0Id.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/R1RggVhA72agIvELiuhWPRS8F0Ip.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/aEHSZBIY-yve10yGis12Zr5DLZod.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/aEHSZBIY-yve10yGis12Zr5DLZop.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/j4xwF_j8iFTVayUMfxLgMnTbencd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/j4xwF_j8iFTVayUMfxLgMnTbencp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/r8LR4nLmg9ai3oHrW1r_-KocQzkd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/r8LR4nLmg9ai3oHrW1r_-KocQzkp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/d1u4eIKNgMuS21WRxXrD0UScuR8d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/d1u4eIKNgMuS21WRxXrD0UScuR8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gjXMbSOzqQJbg7H7bMF0OVGji80d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gjXMbSOzqQJbg7H7bMF0OVGji80p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/p5HYYVUpTuYgZwnT8QkkzaoJraUd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/p5HYYVUpTuYgZwnT8QkkzaoJraUp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/q4FWbcu8zEbneDjWzNwfvfvjQNAd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/q4FWbcu8zEbneDjWzNwfvfvjQNAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/s-04wUzHjOhlMa1CW_zpJwm8iDMd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/s-04wUzHjOhlMa1CW_zpJwm8iDMp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/fjRQtWiSIy7hIlj-Kmk87M7s21k/NjSPEMsIuLUyIpr2u1Js5bVPsOsd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/fjRQtWiSIy7hIlj-Kmk87M7s21k/NjSPEMsIuLUyIpr2u1Js5bVPsOsp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/RMvf4mEDuznAOqU6SKNmIWErfxgd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/RMvf4mEDuznAOqU6SKNmIWErfxgp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/ZTr3GAe6p03ZVs2FdKKE0JsiFMQd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/ZTr3GAe6p03ZVs2FdKKE0JsiFMQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/uIbyU9dPEHKvxjdwx5pD9PDDCZYd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/uIbyU9dPEHKvxjdwx5pD9PDDCZYp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/8h3kimKoV3g5SPdcFPq6bNqde20d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/8h3kimKoV3g5SPdcFPq6bNqde20p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/BT5hWoz-UTefONdqForZyI91O8Yd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/BT5hWoz-UTefONdqForZyI91O8Yp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/BjxNC43HIPP8KZwg_cceb68ikkAd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/BjxNC43HIPP8KZwg_cceb68ikkAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/KocSmEw1PpelhlG7ZNeMUdHVtywd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/KocSmEw1PpelhlG7ZNeMUdHVtywp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/QMJD9OLFzxcTTbPOoh-ahQ4zTRUd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/QMJD9OLFzxcTTbPOoh-ahQ4zTRUp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/R0IsxKENiOKovWZXASFjrmpbBCYd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/R0IsxKENiOKovWZXASFjrmpbBCYp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/ZN2RlSIbyWXhOxbxxI4hOawbMD4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/ZN2RlSIbyWXhOxbxxI4hOawbMD4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/iMwdHOXOBiBXhnA_li8gtEJVTjcd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/iMwdHOXOBiBXhnA_li8gtEJVTjcp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/rh0jHbNfmojECiiHH7BQHmZTsWkd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/rh0jHbNfmojECiiHH7BQHmZTsWkp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/rnpMu7jn2QWt_rQcz8FJ-MxGzVId.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/rnpMu7jn2QWt_rQcz8FJ-MxGzVIp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/6x1BhZX_fLnKpcwqra0qFwv1jIgp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/6xhH2l9GP9loT6TdFn_Mo65sDHgp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/EEtUlUb-dLAdf0KpMVivaUlztwAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/HoHDHQ_WvHAAKj5aJOrvrg_vpt8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/KAXfQgCar2Yb8zOxgvf9hdmLP1Ep.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/NmGqIpAwUJcXFyLjFAGnU9uyN5Yp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/WZRuNzqc-Db7NcQAZO8Y-R8U9ccp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/fjRQtWiSIy7hIlj-Kmk87M7s21kp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/qaw0eS1zuuY1ar9TdPn1GMfrjbQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/rootp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/uuid-366ca619-578a-4bc0-8012-bfa62d28c37f.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/uuid-768d5a75-b789-410a-bd37-37618930aace.xml: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------