commit 2f97a4c4c48ed2dee60486838588e6b94d9aa535 Author: svxf Date: Tue Apr 9 15:01:16 2019 +0200 init diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..0f88f6b --- /dev/null +++ b/Pipfile @@ -0,0 +1,17 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +numpy = "*" +scipy = "*" +sympy = "*" +pytest = "*" +pandas = "*" +cachier = "*" + +[dev-packages] + +[requires] +python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..8ade882 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,237 @@ +{ + "_meta": { + "hash": { + "sha256": "645ddde7fd5f497ea131e2195b311a8f0818328bbb2514c82599f6c69bdf6cda" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "argh": { + "hashes": [ + "sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3", + "sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65" + ], + "version": "==0.26.2" + }, + "atomicwrites": { + "hashes": [ + "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", + "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" + ], + "version": "==1.3.0" + }, + "attrs": { + "hashes": [ + "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", + "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" + ], + "version": "==19.1.0" + }, + "cachier": { + "hashes": [ + "sha256:2d195f2f0767f5149533987aab5a7bb0f8c2264d88a4ef440dbf09628b2a9f4b" + ], + "index": "pypi", + "version": "==1.2.5" + }, + "more-itertools": { + "hashes": [ + "sha256:0125e8f60e9e031347105eb1682cef932f5e97d7b9a1a28d9bf00c22a5daef40", + "sha256:590044e3942351a1bdb1de960b739ff4ce277960f2425ad4509446dbace8d9d1" + ], + "markers": "python_version > '2.7'", + "version": "==6.0.0" + }, + "mpmath": { + "hashes": [ + "sha256:fc17abe05fbab3382b61a123c398508183406fa132e0223874578e20946499f6" + ], + "version": "==1.1.0" + }, + "numpy": { + "hashes": [ + "sha256:1980f8d84548d74921685f68096911585fee393975f53797614b34d4f409b6da", + "sha256:22752cd809272671b273bb86df0f505f505a12368a3a5fc0aa811c7ece4dfd5c", + "sha256:23cc40313036cffd5d1873ef3ce2e949bdee0646c5d6f375bf7ee4f368db2511", + "sha256:2b0b118ff547fecabc247a2668f48f48b3b1f7d63676ebc5be7352a5fd9e85a5", + "sha256:3a0bd1edf64f6a911427b608a894111f9fcdb25284f724016f34a84c9a3a6ea9", + "sha256:3f25f6c7b0d000017e5ac55977a3999b0b1a74491eacb3c1aa716f0e01f6dcd1", + "sha256:4061c79ac2230594a7419151028e808239450e676c39e58302ad296232e3c2e8", + "sha256:560ceaa24f971ab37dede7ba030fc5d8fa173305d94365f814d9523ffd5d5916", + "sha256:62be044cd58da2a947b7e7b2252a10b42920df9520fc3d39f5c4c70d5460b8ba", + "sha256:6c692e3879dde0b67a9dc78f9bfb6f61c666b4562fd8619632d7043fb5b691b0", + "sha256:6f65e37b5a331df950ef6ff03bd4136b3c0bbcf44d4b8e99135d68a537711b5a", + "sha256:7a78cc4ddb253a55971115f8320a7ce28fd23a065fc33166d601f51760eecfa9", + "sha256:80a41edf64a3626e729a62df7dd278474fc1726836552b67a8c6396fd7e86760", + "sha256:893f4d75255f25a7b8516feb5766c6b63c54780323b9bd4bc51cdd7efc943c73", + "sha256:972ea92f9c1b54cc1c1a3d8508e326c0114aaf0f34996772a30f3f52b73b942f", + "sha256:9f1d4865436f794accdabadc57a8395bd3faa755449b4f65b88b7df65ae05f89", + "sha256:9f4cd7832b35e736b739be03b55875706c8c3e5fe334a06210f1a61e5c2c8ca5", + "sha256:adab43bf657488300d3aeeb8030d7f024fcc86e3a9b8848741ea2ea903e56610", + "sha256:bd2834d496ba9b1bdda3a6cf3de4dc0d4a0e7be306335940402ec95132ad063d", + "sha256:d20c0360940f30003a23c0adae2fe50a0a04f3e48dc05c298493b51fd6280197", + "sha256:d3b3ed87061d2314ff3659bb73896e622252da52558f2380f12c421fbdee3d89", + "sha256:dc235bf29a406dfda5790d01b998a1c01d7d37f449128c0b1b7d1c89a84fae8b", + "sha256:fb3c83554f39f48f3fa3123b9c24aecf681b1c289f9334f8215c1d3c8e2f6e5b" + ], + "index": "pypi", + "version": "==1.16.2" + }, + "pandas": { + "hashes": [ + "sha256:071e42b89b57baa17031af8c6b6bbd2e9a5c68c595bc6bf9adabd7a9ed125d3b", + "sha256:17450e25ae69e2e6b303817bdf26b2cd57f69595d8550a77c308be0cd0fd58fa", + "sha256:17916d818592c9ec891cbef2e90f98cc85e0f1e89ed0924c9b5220dc3209c846", + "sha256:2538f099ab0e9f9c9d09bbcd94b47fd889bad06dc7ae96b1ed583f1dc1a7a822", + "sha256:366f30710172cb45a6b4f43b66c220653b1ea50303fbbd94e50571637ffb9167", + "sha256:42e5ad741a0d09232efbc7fc648226ed93306551772fc8aecc6dce9f0e676794", + "sha256:4e718e7f395ba5bfe8b6f6aaf2ff1c65a09bb77a36af6394621434e7cc813204", + "sha256:4f919f409c433577a501e023943e582c57355d50a724c589e78bc1d551a535a2", + "sha256:4fe0d7e6438212e839fc5010c78b822664f1a824c0d263fd858f44131d9166e2", + "sha256:5149a6db3e74f23dc3f5a216c2c9ae2e12920aa2d4a5b77e44e5b804a5f93248", + "sha256:627594338d6dd995cfc0bacd8e654cd9e1252d2a7c959449228df6740d737eb8", + "sha256:83c702615052f2a0a7fb1dd289726e29ec87a27272d775cb77affe749cca28f8", + "sha256:8c872f7fdf3018b7891e1e3e86c55b190e6c5cee70cab771e8f246c855001296", + "sha256:90f116086063934afd51e61a802a943826d2aac572b2f7d55caaac51c13db5b5", + "sha256:a3352bacac12e1fc646213b998bce586f965c9d431773d9e91db27c7c48a1f7d", + "sha256:bcdd06007cca02d51350f96debe51331dec429ac8f93930a43eb8fb5639e3eb5", + "sha256:c1bd07ebc15285535f61ddd8c0c75d0d6293e80e1ee6d9a8d73f3f36954342d0", + "sha256:c9a4b7c55115eb278c19aa14b34fcf5920c8fe7797a09b7b053ddd6195ea89b3", + "sha256:cc8fc0c7a8d5951dc738f1c1447f71c43734244453616f32b8aa0ef6013a5dfb", + "sha256:d7b460bc316064540ce0c41c1438c416a40746fd8a4fb2999668bf18f3c4acf1" + ], + "index": "pypi", + "version": "==0.24.2" + }, + "pathtools": { + "hashes": [ + "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0" + ], + "version": "==0.1.2" + }, + "pluggy": { + "hashes": [ + "sha256:19ecf9ce9db2fce065a7a0586e07cfb4ac8614fe96edf628a264b1c70116cf8f", + "sha256:84d306a647cc805219916e62aab89caa97a33a1dd8c342e87a37f91073cd4746" + ], + "version": "==0.9.0" + }, + "portalocker": { + "hashes": [ + "sha256:3fb35648a9e03f267e54c6186513abbd1cdd321c305502545a3550eea8b2923f", + "sha256:d98cdcdbd8c590ee4c93fb4149b2e76030ea6c36d6fdfec122e6656ebf90086f" + ], + "version": "==1.4.0" + }, + "py": { + "hashes": [ + "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", + "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" + ], + "version": "==1.8.0" + }, + "pytest": { + "hashes": [ + "sha256:592eaa2c33fae68c7d75aacf042efc9f77b27c08a6224a4f59beab8d9a420523", + "sha256:ad3ad5c450284819ecde191a654c09b0ec72257a2c711b9633d677c71c9850c4" + ], + "index": "pypi", + "version": "==4.3.1" + }, + "python-dateutil": { + "hashes": [ + "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", + "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" + ], + "version": "==2.8.0" + }, + "pytz": { + "hashes": [ + "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", + "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" + ], + "version": "==2018.9" + }, + "pyyaml": { + "hashes": [ + "sha256:1adecc22f88d38052fb787d959f003811ca858b799590a5eaa70e63dca50308c", + "sha256:436bc774ecf7c103814098159fbb84c2715d25980175292c648f2da143909f95", + "sha256:460a5a4248763f6f37ea225d19d5c205677d8d525f6a83357ca622ed541830c2", + "sha256:5a22a9c84653debfbf198d02fe592c176ea548cccce47553f35f466e15cf2fd4", + "sha256:7a5d3f26b89d688db27822343dfa25c599627bc92093e788956372285c6298ad", + "sha256:9372b04a02080752d9e6f990179a4ab840227c6e2ce15b95e1278456664cf2ba", + "sha256:a5dcbebee834eaddf3fa7366316b880ff4062e4bcc9787b78c7fbb4a26ff2dd1", + "sha256:aee5bab92a176e7cd034e57f46e9df9a9862a71f8f37cad167c6fc74c65f5b4e", + "sha256:c51f642898c0bacd335fc119da60baae0824f2cde95b0330b56c0553439f0673", + "sha256:c68ea4d3ba1705da1e0d85da6684ac657912679a649e8868bd850d2c299cce13", + "sha256:e23d0cc5299223dcc37885dae624f382297717e459ea24053709675a976a3e19" + ], + "version": "==5.1" + }, + "scipy": { + "hashes": [ + "sha256:014cb900c003b5ac81a53f2403294e8ecf37aedc315b59a6b9370dce0aa7627a", + "sha256:281a34da34a5e0de42d26aed692ab710141cad9d5d218b20643a9cb538ace976", + "sha256:588f9cc4bfab04c45fbd19c1354b5ade377a8124d6151d511c83730a9b6b2338", + "sha256:5a10661accd36b6e2e8855addcf3d675d6222006a15795420a39c040362def66", + "sha256:628f60be272512ca1123524969649a8cb5ae8b31cca349f7c6f8903daf9034d7", + "sha256:6dcc43a88e25b815c2dea1c6fac7339779fc988f5df8396e1de01610604a7c38", + "sha256:70e37cec0ac0fe95c85b74ca4e0620169590fd5d3f44765f3c3a532cedb0e5fd", + "sha256:7274735fb6fb5d67d3789ddec2cd53ed6362539b41aa6cc0d33a06c003aaa390", + "sha256:78e12972e144da47326958ac40c2bd1c1cca908edc8b01c26a36f9ffd3dce466", + "sha256:790cbd3c8d09f3a6d9c47c4558841e25bac34eb7a0864a9def8f26be0b8706af", + "sha256:79792c8fe8e9d06ebc50fe23266522c8c89f20aa94ac8e80472917ecdce1e5ba", + "sha256:865afedf35aaef6df6344bee0de391ee5e99d6e802950a237f9fb9b13e441f91", + "sha256:870fd401ec7b64a895cff8e206ee16569158db00254b2f7157b4c9a5db72c722", + "sha256:963815c226b29b0176d5e3d37fc9de46e2778ce4636a5a7af11a48122ef2577c", + "sha256:9726791484f08e394af0b59eb80489ad94d0a53bbb58ab1837dcad4d58489863", + "sha256:9de84a71bb7979aa8c089c4fb0ea0e2ed3917df3fb2a287a41aaea54bbad7f5d", + "sha256:b2c324ddc5d6dbd3f13680ad16a29425841876a84a1de23a984236d1afff4fa6", + "sha256:b86ae13c597fca087cb8c193870507c8916cefb21e52e1897da320b5a35075e5", + "sha256:ba0488d4dbba2af5bf9596b849873102d612e49a118c512d9d302ceafa36e01a", + "sha256:d78702af4102a3a4e23bb7372cec283e78f32f5573d92091aa6aaba870370fe1", + "sha256:def0e5d681dd3eb562b059d355ae8bebe27f5cc455ab7c2b6655586b63d3a8ea", + "sha256:e085d1babcb419bbe58e2e805ac61924dac4ca45a07c9fa081144739e500aa3c", + "sha256:e2cfcbab37c082a5087aba5ff00209999053260441caadd4f0e8f4c2d6b72088", + "sha256:e742f1f5dcaf222e8471c37ee3d1fd561568a16bb52e031c25674ff1cf9702d5", + "sha256:f06819b028b8ef9010281e74c59cb35483933583043091ed6b261bb1540f11cc", + "sha256:f15f2d60a11c306de7700ee9f65df7e9e463848dbea9c8051e293b704038da60", + "sha256:f31338ee269d201abe76083a990905473987371ff6f3fdb76a3f9073a361cf37", + "sha256:f6b88c8d302c3dac8dff7766955e38d670c82e0d79edfc7eae47d6bb2c186594" + ], + "index": "pypi", + "version": "==1.2.1" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "version": "==1.12.0" + }, + "sympy": { + "hashes": [ + "sha256:e1319b556207a3758a0efebae14e5e52c648fc1db8975953b05fff12b6871b54" + ], + "index": "pypi", + "version": "==1.3" + }, + "watchdog": { + "hashes": [ + "sha256:965f658d0732de3188211932aeb0bb457587f04f63ab4c1e33eab878e9de961d" + ], + "version": "==0.9.0" + } + }, + "develop": {} +} diff --git a/pub2.ipynb b/pub2.ipynb new file mode 100644 index 0000000..9af11d3 --- /dev/null +++ b/pub2.ipynb @@ -0,0 +1,113 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Populating the interactive namespace from numpy and matplotlib\n" + ] + } + ], + "source": [ + "%pylab inline" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path[0:0] = ['src/']" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "from solvers.implicit import solve_implicit\n", + "\n", + "from util import Grid" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "grid = Grid(100, 500)\n", + "\n", + "solution = solve(grid)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot(grid.xs, solution[-1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "solve" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/roots128.pickle b/roots128.pickle new file mode 100644 index 0000000..f4b06f5 Binary files /dev/null and b/roots128.pickle differ diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/consts.py b/src/consts.py new file mode 100644 index 0000000..3220382 --- /dev/null +++ b/src/consts.py @@ -0,0 +1,5 @@ +l = 20 +T = 100 + +D = 0.6 +H = 4 diff --git a/src/runnables/__init__.py b/src/runnables/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/runnables/compare.py b/src/runnables/compare.py new file mode 100644 index 0000000..1e0ab43 --- /dev/null +++ b/src/runnables/compare.py @@ -0,0 +1,86 @@ +import itertools + +import util +from solvers import solvers, solve_explicit, solve_implicit, solve_implicit_improved, solve_crank_nicolson, \ + solve_crank_nicolson_improved +from solvers.theoretical import solve_theoretical +from util import Grid + +import numpy as np + + +def test_order(errors, next_params): + errors = dict(errors) + for params in list(errors.keys()): + if params not in errors: + continue + + # chain start + param_chain = [] + error_chain = [] + + while params in errors: + param_chain.append(params) + error_chain.append(errors[params]) + + del errors[params] + + params = next_params(params) + + if len(param_chain) < 2: + continue + + print(' ', ' -> '.join(map(str, param_chain))) + e = np.array(error_chain, dtype=float) + ed = e[:-1] / e[1:] + print(' ', ' '.join([f'{i:6.2f}' for i in ed])) + + +def test_solver(solver, Is, Ks): + param_pairs = itertools.product(Is, Ks) + param_pairs = sorted(param_pairs, key=np.prod) + + errors_mse = {} + errors_mae = {} + errors_mae_last = {} + + for I, K in param_pairs: + grid = Grid(I, K) + + solution = solver(grid) + if solution is None: + continue + + reference = solve_theoretical(grid) + + errors_mse[(I, K)] = util.mse(reference, solution) + errors_mae[(I, K)] = util.mae(reference, solution) + errors_mae_last[(I, K)] = util.mae_last(reference, solution) + + print() + print() + print(solver.__name__) + + print('O(h_x, h_t) MAEL SHOULD BE >=2') + test_order(errors_mae_last, next_params=lambda params: (params[0] * 2, params[1] * 2)) + + print(f'O(h_x, h_t^2) MAEL SHOULD BE >=4') + test_order(errors_mae_last, next_params=lambda params: (params[0] * 4, params[1] * 2)) + + print(f'O(h_x^2, h_t) MAEL SHOULD BE >=4') + test_order(errors_mae_last, next_params=lambda params: (params[0] * 2, params[1] * 4)) + + +if __name__ == '__main__': + # Is = [4, 8, 16, 32, 64, 128, 256, 512] + # Ks = [4, 8, 16, 32, 64, 128, 256, 512] + # Is = [4, 8, 16, 32, 64, 128, 256, 512] + # Ks = [32, 64, 128, 256, 512, 1024, 2048, 4096] + Is = [4, 8, 16, 32, 64] + Ks = [32, 64, 128, 256, 512, 1024] + + test_solver(solve_explicit, Is, Ks) + test_solver(solve_implicit, Is, Ks) + test_solver(solve_implicit_improved, Is, Ks) + test_solver(solve_crank_nicolson, Is, Ks) + test_solver(solve_crank_nicolson_improved, Is, Ks) diff --git a/src/runnables/run_all.py b/src/runnables/run_all.py new file mode 100644 index 0000000..e04c796 --- /dev/null +++ b/src/runnables/run_all.py @@ -0,0 +1,20 @@ +import util +from solvers import solvers +from solvers.theoretical import solve_theoretical +from util import Grid + +if __name__ == '__main__': + grid = Grid(16, 128) + + reference = solve_theoretical(grid) + + print() + print(grid) + + for solver in solvers: + solution = solver(grid) + + mse = util.mse(reference, solution) + mae = util.mae(reference, solution) + + print(f'{solver.__name__:30} {mse:.4e} {mae:.4e}') diff --git a/src/runnables/where_mae.py b/src/runnables/where_mae.py new file mode 100644 index 0000000..76bf913 --- /dev/null +++ b/src/runnables/where_mae.py @@ -0,0 +1,27 @@ +from solvers import solvers, solve_theoretical +from util import Grid + +import numpy as np + +if __name__ == '__main__': + I = 16 + K = 512 + + grid = Grid(I, K) + + for solver in solvers: + solution = solver(grid) + if solution is None: + continue + + print(solver.__name__) + + reference = solve_theoretical(grid) + + e = np.abs(reference - solution) + + flat_indices = np.argsort(e, axis=None) + + for index in flat_indices[-10:]: + i, j = np.unravel_index(index, e.shape) + print(f'{i:4} {j:4} {e[i, j]}') diff --git a/src/solvers/__init__.py b/src/solvers/__init__.py new file mode 100644 index 0000000..1c3741c --- /dev/null +++ b/src/solvers/__init__.py @@ -0,0 +1,12 @@ +from solvers.crank_nicolson import solve_crank_nicolson, solve_crank_nicolson_improved +from solvers.explicit import solve_explicit +from solvers.implicit import solve_implicit, solve_implicit_improved +from solvers.theoretical import solve_theoretical + +solvers = [ + solve_explicit, + solve_implicit, + solve_implicit_improved, + solve_crank_nicolson, + solve_crank_nicolson_improved, +] diff --git a/src/solvers/crank_nicolson.py b/src/solvers/crank_nicolson.py new file mode 100644 index 0000000..7aab7af --- /dev/null +++ b/src/solvers/crank_nicolson.py @@ -0,0 +1,102 @@ +import numpy as np +import scipy.sparse +import scipy.sparse.linalg + +import consts +from util import Grid + + +#@cachier(stale_after=datetime.timedelta(hours=1)) +def solve_crank_nicolson(grid: Grid) -> np.ndarray: + ug = np.zeros((grid.K + 1, grid.I + 1), dtype=float) + + ug[0, :] = np.sin(np.pi * grid.xs / consts.l) ** 2 * 4 / 10 + + for k in range(1, grid.K + 1): + diags = { + -1: np.zeros(grid.I + 1, dtype=float), + 0: np.zeros(grid.I + 1, dtype=float), + +1: np.zeros(grid.I + 1, dtype=float), + } + b = np.zeros(grid.I + 1, dtype=float) + + # left + diags[0][0] = consts.H * grid.h_x + 1 + diags[+1][0] = -1 + + # middle + for i in range(1, grid.I): + diags[-1][i] = grid.gamma + diags[0][i] = - 2 * grid.gamma - 2 + diags[+1][i] = grid.gamma + b[i] = -( + ug[k - 1][i - 1] * grid.gamma + + ug[k - 1][i] * (-2 * grid.gamma + 2) + + ug[k - 1][i + 1] * grid.gamma + ) + + # right + diags[0][grid.I] = consts.H * grid.h_x + 1 + diags[-1][grid.I] = -1 + + A = scipy.sparse.diags([ + diags[-1][1:], + diags[0], + diags[+1][:-1], + ], [-1, 0, 1], format='csc') + + ug[k, :] = scipy.sparse.linalg.spsolve(A, b) + + return ug + + +#@cachier(stale_after=datetime.timedelta(hours=1)) +def solve_crank_nicolson_improved(grid: Grid) -> np.ndarray: + ug = np.zeros((grid.K + 1, grid.I + 1), dtype=float) + + ug[0, :] = np.sin(np.pi * grid.xs / consts.l) ** 2 * 4 / 10 + + for k in range(1, grid.K + 1): + diags = { + -1: np.zeros(grid.I + 1, dtype=float), + 0: np.zeros(grid.I + 1, dtype=float), + +1: np.zeros(grid.I + 1, dtype=float), + } + b = np.zeros(grid.I + 1, dtype=float) + + # left + diags[0][0] = consts.H * grid.gamma * grid.h_x + grid.gamma + 1 + diags[+1][0] = - grid.gamma + b[0] = ( + (- consts.H * grid.gamma * grid.h_x - grid.gamma + 1) * ug[k - 1, 0] + + grid.gamma * ug[k - 1, 1] + ) + + # middle + for i in range(1, grid.I): + diags[-1][i] = grid.gamma + diags[0][i] = - 2 * grid.gamma - 2 + diags[+1][i] = grid.gamma + b[i] = -( + ug[k - 1][i - 1] * grid.gamma + + ug[k - 1][i] * (-2 * grid.gamma + 2) + + ug[k - 1][i + 1] * grid.gamma + ) + + # right + diags[0][grid.I] = consts.H * grid.gamma * grid.h_x + grid.gamma + 1 + diags[-1][grid.I] = - grid.gamma + b[grid.I] = ( + (- consts.H * grid.gamma * grid.h_x - grid.gamma + 1) * ug[k - 1, grid.I] + + grid.gamma * ug[k - 1, grid.I - 1] + ) + + A = scipy.sparse.diags([ + diags[-1][1:], + diags[0], + diags[+1][:-1], + ], [-1, 0, 1], format='csc') + + ug[k, :] = scipy.sparse.linalg.spsolve(A, b) + + return ug diff --git a/src/solvers/explicit.py b/src/solvers/explicit.py new file mode 100644 index 0000000..3587728 --- /dev/null +++ b/src/solvers/explicit.py @@ -0,0 +1,32 @@ +from typing import Optional + +import numpy as np + +import consts +from util import Grid + + +#@cachier(stale_after=datetime.timedelta(hours=1)) +def solve_explicit(grid: Grid) -> Optional[np.ndarray]: + if grid.gamma > 1 / 2: + return None + + ug = np.zeros((grid.K + 1, grid.I + 1), dtype=float) + + ug[0, :] = np.sin(np.pi * grid.xs / consts.l) ** 2 * 4 / 10 + + for k in range(1, grid.K + 1): + # middle + ug[k, 1: grid.I] = ( + grid.gamma * ug[k - 1, 0: grid.I - 1] + + (-2 * grid.gamma + 1) * ug[k - 1, 1: grid.I] + + grid.gamma * ug[k - 1, 2: grid.I + 1] + ) + + # left + ug[k, 0] = ug[k, 1] / (consts.H * grid.h_x + 1) + + # right + ug[k, grid.I] = ug[k, grid.I - 1] / (consts.H * grid.h_x + 1) + + return ug diff --git a/src/solvers/implicit.py b/src/solvers/implicit.py new file mode 100644 index 0000000..56abf7a --- /dev/null +++ b/src/solvers/implicit.py @@ -0,0 +1,95 @@ +import numpy as np +import scipy.sparse +import scipy.sparse.linalg + +import consts + + +#@cachier(stale_after=datetime.timedelta(hours=1)) +def solve_implicit(grid) -> np.ndarray: + ug = np.zeros((grid.K + 1, grid.I + 1), dtype=float) + + ug[0, :] = np.sin(np.pi * grid.xs / consts.l) ** 2 * 4 / 10 + + for k in range(1, grid.K + 1): + diags = { + -1: np.zeros(grid.I + 1, dtype=float), + 0: np.zeros(grid.I + 1, dtype=float), + +1: np.zeros(grid.I + 1, dtype=float), + } + b = np.zeros(grid.I + 1, dtype=float) + + # left + diags[0][0] = consts.H * grid.h_x + 1 + diags[+1][0] = -1 + + # middle + for i in range(1, grid.I): + diags[-1][i] = grid.gamma + diags[0][i] = - 2 * grid.gamma - 1 + diags[+1][i] = grid.gamma + b[i] = -ug[k - 1, i] + + # right + diags[-1][grid.I] = -1 + diags[0][grid.I] = consts.H * grid.h_x + 1 + + A = scipy.sparse.diags([ + diags[-1][1:], + diags[0], + diags[+1][:-1], + ], [-1, 0, 1], format='csc') + + ug[k, :] = scipy.sparse.linalg.spsolve(A, b) + + return ug + + +#@cachier(stale_after=datetime.timedelta(hours=1)) +def solve_implicit_improved(grid) -> np.ndarray: + ug = np.zeros((grid.K + 1, grid.I + 1), dtype=float) + + ug[0, :] = np.sin(np.pi * grid.xs / consts.l) ** 2 * 4 / 10 + + for k in range(1, grid.K + 1): + diags = { + -1: np.zeros(grid.I + 1, dtype=float), + 0: np.zeros(grid.I + 1, dtype=float), + +1: np.zeros(grid.I + 1, dtype=float), + } + b = np.zeros(grid.I + 1, dtype=float) + + # left + diags[0][0] = ( + 2 * consts.H * grid.gamma * grid.h_x + + 2 * grid.gamma + + 1 + ) + diags[+1][0] = - 2 * grid.gamma + b[0] = ug[k - 1, 0] + + # middle + for i in range(1, grid.I): + diags[-1][i] = grid.gamma + diags[0][i] = - 2 * grid.gamma - 1 + diags[+1][i] = grid.gamma + b[i] = -ug[k - 1, i] + + # right + diags[0][grid.I] = ( + 2 * consts.H * grid.gamma * grid.h_x + + 2 * grid.gamma + + 1 + ) + diags[-1][grid.I] = - 2 * grid.gamma + b[grid.I] = ug[k - 1, grid.I] + + A = scipy.sparse.diags([ + diags[-1][1:], + diags[0], + diags[+1][:-1], + ], [-1, 0, 1], format='csc') + + ug[k, :] = scipy.sparse.linalg.spsolve(A, b) + + return ug diff --git a/src/solvers/theoretical.py b/src/solvers/theoretical.py new file mode 100644 index 0000000..9aa41b2 --- /dev/null +++ b/src/solvers/theoretical.py @@ -0,0 +1,35 @@ +import functools +import pickle + +import numpy as np + +from util import Grid + +with open('./roots128.pickle', 'rb') as file: + roots128 = pickle.load(file) + + +def u_elem128(x, t, alpha_n): + x = np.float128(x) + t = np.float128(t) + alpha_n = np.float128(alpha_n) + return -4 * np.pi ** 2 * (alpha_n * np.cos(alpha_n * x / 10) + 40 * np.sin(alpha_n * x / 10)) * ( + alpha_n * np.sin(2 * alpha_n) - 40 * np.cos(2 * alpha_n) + 40) * np.exp(-3 * alpha_n ** 2 * t / 500) / ( + 5 * (alpha_n ** 2 - np.pi ** 2) * (alpha_n ** 2 * (4 * alpha_n + np.sin(4 * alpha_n)) - 80 * alpha_n * ( + np.cos(4 * alpha_n) - 1) + 6400 * alpha_n - 1600 * np.sin(4 * alpha_n))) + + +@functools.lru_cache(maxsize=1000000) +def u128(x, t, root_n=len(roots128)): + return sum(u_elem128(x, t, roots128[:root_n])) + + +#@cachier(stale_after=datetime.timedelta(hours=1)) +def solve_theoretical(grid: Grid) -> np.ndarray: + ug = np.zeros((grid.K + 1, grid.I + 1), dtype=float) + + for k, t in enumerate(grid.ts): + for i, x in enumerate(grid.xs): + ug[k, i] = u128(x, t, 1000) + + return ug diff --git a/src/util.py b/src/util.py new file mode 100644 index 0000000..becba20 --- /dev/null +++ b/src/util.py @@ -0,0 +1,45 @@ +from dataclasses import dataclass, field +import numpy as np + +import consts + + +@dataclass +class Grid: + I: int + K: int + + xs: np.ndarray = field(repr=False, compare=False) + ts: np.ndarray = field(repr=False, compare=False) + + h_x: float = field(repr=False, compare=False) + h_t: float = field(repr=False, compare=False) + + gamma: float = field(repr=False, compare=False) + + def __init__(self, I: int, K: int): + self.I = I + self.K = K + + self.xs = np.linspace(0, consts.l, I + 1) + self.ts = np.linspace(0, consts.T, K + 1) + + self.h_x = consts.l / I + self.h_t = consts.T / K + + self.gamma = consts.D * self.h_t / (self.h_x ** 2) + + def __hash__(self): + return hash((self.I, self.K)) + + +def mse(ug1: np.ndarray, ug2: np.ndarray) -> float: + return np.mean((ug1 - ug2) ** 2) + + +def mae(ug1: np.ndarray, ug2: np.ndarray) -> float: + return np.max(np.abs(ug1 - ug2)) + + +def mae_last(ug1: np.ndarray, ug2: np.ndarray) -> float: + return np.max(np.abs(ug1[-1, :] - ug2[-1, :])) diff --git a/symbolic.ipynb b/symbolic.ipynb new file mode 100644 index 0000000..37cd688 --- /dev/null +++ b/symbolic.ipynb @@ -0,0 +1,945 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Populating the interactive namespace from numpy and matplotlib\n" + ] + } + ], + "source": [ + "%pylab inline" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas\n", + "import sympy as Ω\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from scipy.misc import derivative\n", + "import pickle\n", + "from tqdm import tqdm_notebook as tqdm\n", + "\n", + "from dataclasses import dataclass\n", + "\n", + "import scipy.sparse\n", + "import scipy.sparse.linalg\n", + "\n", + "import functools" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "Ω.init_printing()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "i, k = Ω.symbols('i k')\n", + "I, K = Ω.symbols('I K')\n", + "h_x, h_t = Ω.symbols('h_x h_t')\n", + "l, T, H, D = Ω.symbols('l T H D')" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "u = Ω.IndexedBase('u', shape=(I + 1, K + 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "gamma = Ω.symbols('gamma')\n", + "gamma_val = D * h_t / h_x**2" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "heading_collapsed": true + }, + "source": [ + "## простейшая явная" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\left [ - \\gamma {u}_{k - 1,i + 1} - \\gamma {u}_{k - 1,i - 1} + 2 \\gamma {u}_{k - 1,i} - {u}_{k - 1,i} + {u}_{k,i}, \\quad - H {u}_{k,0} + \\frac{- {u}_{k,0} + {u}_{k,1}}{h_{x}}, \\quad H {u}_{k,I} + \\frac{- {u}_{k,I - 1} + {u}_{k,I}}{h_{x}}\\right ]$$" + ], + "text/plain": [ + "⎡ \n", + "⎢-γ⋅u[k - 1, i + 1] - γ⋅u[k - 1, i - 1] + 2⋅γ⋅u[k - 1, i] - u[k - 1, i] + u[k,\n", + "⎣ \n", + "\n", + " -u[k, 0] + u[k, 1] -u[k, I - 1] + u[k, I]⎤\n", + " i], -H⋅u[k, 0] + ──────────────────, H⋅u[k, I] + ──────────────────────⎥\n", + " hₓ hₓ ⎦" + ] + }, + "execution_count": 91, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "eqs = [\n", + " (u[k, i] - u[k - 1, i]) / h_t - D * (u[k - 1, i + 1] - 2 * u[k - 1, i] + u[k - 1, i - 1]) / (h_x**2),\n", + " (u[k, 1] - u[k, 0]) / h_x - H * u[k, 0],\n", + " (u[k, I] - u[k, I - 1]) / h_x + H * u[k, I],\n", + "]\n", + "eqs[0] = (eqs[0] * h_t).expand().subs({gamma_val:gamma})\n", + "eqs" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "### $i=1,I-1$" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\gamma {u}_{k - 1,i + 1} + \\gamma {u}_{k - 1,i - 1} + \\left(- 2 \\gamma + 1\\right) {u}_{k - 1,i}$$" + ], + "text/plain": [ + "γ⋅u[k - 1, i + 1] + γ⋅u[k - 1, i - 1] + (-2⋅γ + 1)⋅u[k - 1, i]" + ] + }, + "execution_count": 92, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Ω.solve(eqs[0], u[k, i])[0].expand().subs({gamma_val:gamma}).collect([\n", + " u[k-1, i-1],\n", + " u[k-1, i],\n", + " u[k-1, i+1],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "### $i=0$" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAADYAAAAjCAYAAADfXvn1AAAABHNCSVQICAgIfAhkiAAAAuBJREFUWIXt2E+IV1UUwPHPmATKkFILBWVENFES/c0fkRaJgTuJ2thGCEFoYYtoIZS4KF0YLvy3F1xFyVSkaEEJQlgbJzVCzP5AVCBI6aAWaKSLc19zf2/e2G98v9/MLH5feLx7zzv33nPeufe9ey5dKtmEu3g8ky3GfaycFosSs2q278dl4Vwu+wtXa/Zdi7qONXCxJOvHd/gXL+JQi319jBsYrmkT2hOxSyVZ7uyaiucTcRiv1LTnP+o4NgcrjI/YOmPOFI49gU/w6kP6O4tbNexpYnaNtsvwGH7IZBvEx6NwdhX+xqd4G5/XGG/KWCjW0UupPoTvk6xXRPQGLuCZFvvcaAassWvYhaP4FW/gffyE21iNr9MY/9Qzc2axHW9hACMiigVnsKiizUZtilgnOYwXUnk7jqdyD34RUzXnC1wX/8Df8OwU2NhWVuHAdBvRpUuXevSk+/1ptaJL53lX/HdmLOUt1Rm8V6H3stgDzkv1qjxsqtiAE/hdLKFtVUplxwZwvkJvCD9iNNUbWs+zWuWYyAD+j16RyL4uModKcseWYb6JHRtJ5YVYII4DTuOO2Pg+34JR7eC02HwPi1lUSe7YYFL8pqTTY2wjS0QLXsNBrBVvcEZtk/JEc1A4OlEWmzs2KtbdtSQbxr5OGPio5BEbwClxjpFfu8UiLSLZwEljTsFysQYnwy6RtxXX1grZc5Pss5I/sLNCvl/zUdoV7CjpnNB8GnUO61P5qEhCyzwpXkhxfYgjJVk5tSlz2wRfxWIqLk0DjVTo5OtrLp4W6X5OPz7K6nvxJr4U6/ZgRb9/pqvgVqpPNvKVFFNxMN3LHw7C6MKxNen+bfb8Kc0HOPAZ+rDZ+OjWpVcsh4awvy+V+3Kl3LGfcbPUyRLNkWyIU6k7mU4/7okT4YJ1qd1oetZOhsSMuSCm6jupvKfN44xjkfh5LxUzYHWnB5wK5uArse2BLfhg+szp0qVLp3gArXKVkSmRbzYAAAAASUVORK5CYII=\n", + "text/latex": [ + "$$\\frac{{u}_{k,1}}{H h_{x} + 1}$$" + ], + "text/plain": [ + "u[k, 1] \n", + "────────\n", + "H⋅hₓ + 1" + ] + }, + "execution_count": 93, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Ω.solve(eqs[1], u[k, 0])[0].expand().subs({gamma_val:gamma})" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "### $i=I$" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAADYAAAAjCAYAAADfXvn1AAAABHNCSVQICAgIfAhkiAAAAxZJREFUWIXt2FuIVlUUwPHfRAgTQ0U+FBgTQyUKYt9cJAoSg+olIhDyoUIEoYd8kAKhhoguUNFDZj2G0JNUTEVG0kNCFNZLkyYW4Q0EK6HroBVUND2sffj2nDnfbb75ZoS+PxzOPmuvvfdaZ6995X/KHfgLKzLZtZjFmmWxqE0uaZE/im+Ec7nsDxzvlVGLQSvHajhSko3iGP7FvXi5zbYexXMdWVfnXfyKqXYLtNNjX5VkubPrK/IbsU78kIWwB1s7KdDMsUGsNr/HNqg7Uzh2Od7DQ03q68axj3F+gWUrDZkVk0XBxiS7NX0fw1ocwp1N6hoQobSiiU4rNukgFC9tkveTcGICZ9P7tSQ7Knp0FfbhQXzdpK4R/GDuJEREQ5UNd+H71uY3pplj5zCJvXgVn+AN3I8LIiQ/F87906KdRmFY69DeJWE7HscYpjGU5R0UDhdM4sku29ukg1Dshj24J6W3462UHsAZEaoF+7C5i7Y+wo9i/TyLW7qoa8GsxUvL0XCfPn2WjoH0nl1WK/r0nhfE2nLRUt7dHxSLaZkt4vx1RfquOqctFRuxH9+JIbStSqns2Bi+qNCbwEnMpO+a9s9h7fI6nmpDb0jsO3fiz0ZKuWPX40qNHZtO6WtwtdipH8DvOIXb2zBqMTgg9p5TIooqyR0bT4pflnQG1De61HfkO7AbN4k/eFFto/Jjy7hwtNFJNXdsRoy7c0k2hed7YeBCyXtsDB+Ie478eUIM0qIna3hf3Sm4QYzBTpgU57rieaBCdluHdVbyM3ZVyF8096rtWzxc0tlv7m3VIdyc0nvxSEW9V4kfUjxv45WSbLCiXM4FDWbFIhRHUkPTFTr5+LoMN+JwSWcU72Tfz+IxfCrG7e6Ken9JT8H59N1pz1dShOJ4epcnDsLowrH16X00y18pLnzyde1DDONu83u3W4bEcKgJ+4dTejhXyh07jd9KlVxnbk/WcEJM8QWj+FvcGBdsSOVmUt5iMiEi5rAI1adT+plFbmceq8TiPSIiYF2vG1wKBvGZ2PbAfXhz+czp06dPr/gPRuyh+uS9hDQAAAAASUVORK5CYII=\n", + "text/latex": [ + "$$\\frac{{u}_{k,I - 1}}{H h_{x} + 1}$$" + ], + "text/plain": [ + "u[k, I - 1]\n", + "───────────\n", + " H⋅hₓ + 1 " + ] + }, + "execution_count": 94, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Ω.solve(eqs[2], u[k, I])[0].expand().subs({gamma_val:gamma})" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "heading_collapsed": true + }, + "source": [ + "## простейшая неявная" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\left [ - \\gamma {u}_{k,i + 1} - \\gamma {u}_{k,i - 1} + 2 \\gamma {u}_{k,i} - {u}_{k - 1,i} + {u}_{k,i}, \\quad - H {u}_{k,0} + \\frac{- {u}_{k,0} + {u}_{k,1}}{h_{x}}, \\quad H {u}_{k,I} + \\frac{- {u}_{k,I - 1} + {u}_{k,I}}{h_{x}}\\right ]$$" + ], + "text/plain": [ + "⎡ \n", + "⎢-γ⋅u[k, i + 1] - γ⋅u[k, i - 1] + 2⋅γ⋅u[k, i] - u[k - 1, i] + u[k, i], -H⋅u[k,\n", + "⎣ \n", + "\n", + " -u[k, 0] + u[k, 1] -u[k, I - 1] + u[k, I]⎤\n", + " 0] + ──────────────────, H⋅u[k, I] + ──────────────────────⎥\n", + " hₓ hₓ ⎦" + ] + }, + "execution_count": 126, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "eqs = [\n", + " (u[k, i] - u[k - 1, i]) / h_t - D * (u[k, i + 1] - 2 * u[k, i] + u[k, i - 1]) / (h_x**2),\n", + " (u[k, 1] - u[k, 0]) / h_x - H * u[k, 0],\n", + " (u[k, I] - u[k, I - 1]) / h_x + H * u[k, I],\n", + "]\n", + "eqs[0] = (eqs[0] * h_t).expand().subs({gamma_val:gamma})\n", + "eqs" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "### $i=1,I-1$" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYEAAAAZCAYAAADXG5K+AAAABHNCSVQICAgIfAhkiAAABx5JREFUeJztnXuIVFUcxz+apesupCYhKWWWj0RwyzaUQsayIiIzK/qjqKGipCwkosheWlJCf5RFFBWxSYKFYiWEFqTpGpWPpIeaaY1RmrZkVmppZX/8zs2ZM2fmnvu+u3M+MNy75zXnfM/v3PO8s+BwOBwOh8PR4LwG7AWas85IDhgHHAVuzTojDofDkQZtwL/APZr7SciDcCmwHTgE7Ac6gFuAninmMQrXAM8Ba4DfkAf86z5xlgK7gZZks+ZwOBzZ8x7wK9CkuU9HHpi7gIXAk8CrKuxRYDHQI71shmYTkt/fgS3YdQLnqXCzks2aw9F9KCKNppBtNhwBGYHMAl4y+F0IXEH1iH8Q8D1S31cnmrtjFAlvX5OA4UiHVcCuEwDpMHbSdWY8OkVcm/SlvHKvAo4AnwCn1Qg/BxH1NuABdT/NEO5U5bc0tpx2X4LqDk77OLkZeTi+YfD7AFiGdBLl/AS8qO4Lml+Y+kyalcA36juDsAixp4sNfo1gg41QxopOYC/wPjINvM8QdphyXwe8gmweAaw3hG1T143xZLNbE1R3cNrHyWTgH+DjgPGOqOvfmnuY+swra9XV1Ak0gg02QhkrOoG1yCjmAHCuIeyzwAnAHcjIaBzQiUyLdbz4n8WW0+5LUN3BaR8XzUArsuxxIEC8XsCN6n655hemPvPKOnWdaPBrBBtshDJWrfX9BWwGRmnuU4DLkXXT9cAAYCiwoUa6nkB6LzkPGSWF4Xm6wdSrBra6g9M+TgYDxyGnYIIwDxgDvAusMPgHqc88sx/4E1n6KCeMDUaxP0jfBrMoY1r4arkAWesaov5uAr4Ffgb6K7fJKszcGmn8AuwxuC8HngqW3//pT7zH1SYC7wA/ImUpBohbUnFsP+0WadroDk77EsG0r7cBOkGFMe0H1OJuFWcL8qCohW19migRv315FLDfGAapI33JK4wNRrE/8LfBEvFqlkUZbYjSdjwqtOxlCLBVXUcDPyCbI6cj56L3KT9vrczUSw5TX6JPk0Gm3gsCZ1nY5x8EkMotAbN9wrUAX6r8BM3TM0A/za0VuBJ56aik+W2ySNNGd8i39rZE0X4HMjq1ZVcdv0Pq2scyrRnAfGSUfxHyIKiFbX2aSMK+wtLEMZ08wthgFPuD9DXLoow2RGk7Hr7teRrSw8wEzkAa3EdUnodepMKYTj/MUH5PaO6DlPto9XezSmcjMu2qxxAVV59em2jHvwPQ+YNwPWo5RaIdR7PRHfKtfRji0D4spyBl67AIO1OF/QI42SK8bX3aUiSe444F7GcCPZF9ix2ae1AbjGJ/EN4Gi4TXLO0yhiFM26nS0nT+t3wEMx+ZLdxJ5fGyUcjpiJ1a3N7A7epeX5NuRUYUXwMjgU+Raeb5VPfSOmOBg8A2n3BdGRvdwWkfJ7uR5ZmRPuHuB55GRo+TkBNAftjWZ54ZiXRa+qg5qA1GsT/IxgbTLmNaVGlp6gS2I0fmrkU2sV6gegf8MHA88gKKRzPyNuUY9bcepxUZRU1FRkQvAzdQPdU04cXN+2mKKNjoDk77ODkKrAYGAmfWCPMwsuG3AVkC6rRM27Y+88x4dV2puQe1wSj2Vx4/TRtMu4xpUaWlaU/gMPAd0ij2Ag8ZwqxAzsmuRnaZW5AG8jkyuuqLbILpXz4cEXEK8GGAjI+l9hreLCpfbe+NNO57y9wuQ343Jc/Y6A750n4u8KBP/EnAqgDflzZLkLd+L0Ue3OXcBDyGPMzXIJvCOiXMm4y29ZkGU9UHZNkCZFO8Xd13UtlePC5Byv625h7UBqPYH9S3waRIsoxZthtrLZdRf+e5DzLF3YVMLdYjU6R+SA+zyhBnK/JyzEHkHHUQtiG/42JiANLQvM8S5Cx2uZv+mzA6edgTAH/dIV/aD0SmzfU+fX3Sz3JPAOTM/h7kDV+d2fifMllVJ22b+rSlSHj7mk39MpQMcU5ERrFvGfyC2mAU+4P6NliPIuE1S7KMcbQbCNd2rLXsQEYANhmxoa9Krw24Hsn8OZZxm1Xc8X4BFe1kszEcB3HrDulqH4Y8aO/9PMDZMaebRH2mxV2IJhdETCeK/UE6NhiVqGUMS9C2Y61lD+TXBjeHypaZ8cgmiTcifxw55zrYIu4EgjWkduw6gRZkCteK9N6PqHv9xZi0SEJ3SFd7W/KmfR9kA3BZjGkmVZ9p0ISMgBfHkFYU+4PkbDBOopYxCFHajrWWI5ARwMLQ2axmOvJyjUcP4E1ks83LUFF971BD3K3Y045dJ1Ag+os3cZKE7pCu9rYUyJf2IC/hPEp8/1QmqfpMg7OQNjQ0hrSi2J8XPwkbjBObMsZFAf+2UyRie76O6o3VNJgDfIV5s7oRyEp3cNonQZb12dVw9hcvXVbPdbjf/c4Kp70jS5z9xYvT0+FwOBwOh8PhcDgcDofD4XA4HA5HFf8B2Sn0Vmz2OcMAAAAASUVORK5CYII=\n", + "text/latex": [ + "$$\\gamma {u}_{k,i + 1} + \\gamma {u}_{k,i - 1} - \\left(2 \\gamma + 1\\right) {u}_{k,i} + {u}_{k - 1,i}$$" + ], + "text/plain": [ + "γ⋅u[k, i + 1] + γ⋅u[k, i - 1] - (2⋅γ + 1)⋅u[k, i] + u[k - 1, i]" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "-eqs[0].collect([\n", + " u[k, i-1],\n", + " u[k, i],\n", + " u[k, i+1],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "### $i=0$" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\left(H h_{x} + 1\\right) {u}_{k,0} - {u}_{k,1}$$" + ], + "text/plain": [ + "(H⋅hₓ + 1)⋅u[k, 0] - u[k, 1]" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(-eqs[1] * h_x).expand().collect([\n", + " u[k, 0],\n", + " u[k, 1],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "### $i=I$" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\left(H h_{x} + 1\\right) {u}_{k,I} - {u}_{k,I - 1}$$" + ], + "text/plain": [ + "(H⋅hₓ + 1)⋅u[k, I] - u[k, I - 1]" + ] + }, + "execution_count": 129, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(eqs[2] * h_x).expand().collect([\n", + " u[k, I-1],\n", + " u[k, I],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "heading_collapsed": true + }, + "source": [ + "## КН" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\left [ - \\gamma {u}_{k - 1,i + 1} - \\gamma {u}_{k - 1,i - 1} + 2 \\gamma {u}_{k - 1,i} - \\gamma {u}_{k,i + 1} - \\gamma {u}_{k,i - 1} + 2 \\gamma {u}_{k,i} - 2 {u}_{k - 1,i} + 2 {u}_{k,i}, \\quad - H {u}_{k,0} + \\frac{- {u}_{k,0} + {u}_{k,1}}{h_{x}}, \\quad H {u}_{k,I} + \\frac{- {u}_{k,I - 1} + {u}_{k,I}}{h_{x}}\\right ]$$" + ], + "text/plain": [ + "⎡ \n", + "⎢-γ⋅u[k - 1, i + 1] - γ⋅u[k - 1, i - 1] + 2⋅γ⋅u[k - 1, i] - γ⋅u[k, i + 1] - γ⋅\n", + "⎣ \n", + "\n", + " -u[k, 0] +\n", + "u[k, i - 1] + 2⋅γ⋅u[k, i] - 2⋅u[k - 1, i] + 2⋅u[k, i], -H⋅u[k, 0] + ──────────\n", + " hₓ\n", + "\n", + " u[k, 1] -u[k, I - 1] + u[k, I]⎤\n", + "────────, H⋅u[k, I] + ──────────────────────⎥\n", + " hₓ ⎦" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "eqs = [\n", + " (u[k, i] - u[k - 1, i]) / h_t - D / 2 * (\n", + " (u[k-1, i + 1] - 2 * u[k-1, i] + u[k-1, i - 1]) +\n", + " (u[k, i + 1] - 2 * u[k, i] + u[k, i - 1])\n", + " ) / (h_x**2),\n", + " (u[k, 1] - u[k, 0]) / h_x - H * u[k, 0],\n", + " (u[k, I] - u[k, I - 1]) / h_x + H * u[k, I],\n", + "]\n", + "eqs[0] = (eqs[0] * 2 * h_t).expand().subs({gamma_val:gamma})\n", + "eqs" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "### $i=1,I-1$" + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\gamma {u}_{k - 1,i + 1} + \\gamma {u}_{k - 1,i - 1} + \\gamma {u}_{k,i + 1} + \\gamma {u}_{k,i - 1} + \\left(- 2 \\gamma - 2\\right) {u}_{k,i} + \\left(- 2 \\gamma + 2\\right) {u}_{k - 1,i}$$" + ], + "text/plain": [ + "γ⋅u[k - 1, i + 1] + γ⋅u[k - 1, i - 1] + γ⋅u[k, i + 1] + γ⋅u[k, i - 1] + (-2⋅γ \n", + "- 2)⋅u[k, i] + (-2⋅γ + 2)⋅u[k - 1, i]" + ] + }, + "execution_count": 123, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(-eqs[0]).collect([\n", + " u[k, i-1],\n", + " u[k, i],\n", + " u[k, i+1],\n", + " u[k-1, i-1],\n", + " u[k-1, i],\n", + " u[k-1, i+1],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "### $i=0$" + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\left(H h_{x} + 1\\right) {u}_{k,0} - {u}_{k,1}$$" + ], + "text/plain": [ + "(H⋅hₓ + 1)⋅u[k, 0] - u[k, 1]" + ] + }, + "execution_count": 124, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(-eqs[1] * h_x).expand().collect([\n", + " u[k, 0],\n", + " u[k, 1],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "### $i=I$" + ] + }, + { + "cell_type": "code", + "execution_count": 125, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\left(H h_{x} + 1\\right) {u}_{k,I} - {u}_{k,I - 1}$$" + ], + "text/plain": [ + "(H⋅hₓ + 1)⋅u[k, I] - u[k, I - 1]" + ] + }, + "execution_count": 125, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(eqs[2] * h_x).expand().collect([\n", + " u[k, I-1],\n", + " u[k, I],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## простейшая неявная повышенного порядка аппроксимации" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\left [ - \\frac{D \\left({u}_{k,i + 1} + {u}_{k,i - 1} - 2 {u}_{k,i}\\right)}{h_{x}^{2}} + \\frac{- {u}_{k - 1,i} + {u}_{k,i}}{h_{t}}, \\quad - H {u}_{k,0} + \\frac{- {u}_{k,-1} + {u}_{k,1}}{2 h_{x}}, \\quad H {u}_{k,I} + \\frac{{u}_{k,I + 1} - {u}_{k,I - 1}}{2 h_{x}}\\right ]$$" + ], + "text/plain": [ + "⎡ D⋅(u[k, i + 1] + u[k, i - 1] - 2⋅u[k, i]) -u[k - 1, i] + u[k, i] \n", + "⎢- ───────────────────────────────────────── + ──────────────────────, -H⋅u[k,\n", + "⎢ 2 hₜ \n", + "⎣ hₓ \n", + "\n", + " -u[k, -1] + u[k, 1] u[k, I + 1] - u[k, I - 1]⎤\n", + " 0] + ───────────────────, H⋅u[k, I] + ─────────────────────────⎥\n", + " 2⋅hₓ 2⋅hₓ ⎥\n", + " ⎦" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "eqs = [\n", + " (u[k, i] - u[k - 1, i]) / h_t - D * (u[k, i + 1] - 2 * u[k, i] + u[k, i - 1]) / (h_x**2),\n", + " (u[k, 1] - u[k, -1]) / (2 * h_x) - H * u[k, 0],\n", + " (u[k, I+1] - u[k, I - 1]) / (2 * h_x) + H * u[k, I],\n", + "]\n", + "# eqs[0] = (eqs[0] * h_t).expand().subs({gamma_val:gamma})\n", + "eqs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### $i=1,I-1$" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\frac{D \\left({u}_{k,i + 1} + {u}_{k,i - 1} - 2 {u}_{k,i}\\right)}{h_{x}^{2}} - \\frac{- {u}_{k - 1,i} + {u}_{k,i}}{h_{t}}$$" + ], + "text/plain": [ + "D⋅(u[k, i + 1] + u[k, i - 1] - 2⋅u[k, i]) -u[k - 1, i] + u[k, i]\n", + "───────────────────────────────────────── - ──────────────────────\n", + " 2 hₜ \n", + " hₓ " + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(-eqs[0]).collect([\n", + " u[k, i-1],\n", + " u[k, i],\n", + " u[k, i+1],\n", + " u[k-1, i-1],\n", + " u[k-1, i],\n", + " u[k-1, i+1],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### $i=0$" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$- \\frac{2 D h_{t} {u}_{k,1}}{h_{x}^{2}} + \\left(\\frac{2 D H h_{t}}{h_{x}} + \\frac{2 D h_{t}}{h_{x}^{2}} + 1\\right) {u}_{k,0} - {u}_{k - 1,0}$$" + ], + "text/plain": [ + " 2⋅D⋅hₜ⋅u[k, 1] ⎛2⋅D⋅H⋅hₜ 2⋅D⋅hₜ ⎞ \n", + "- ────────────── + ⎜──────── + ────── + 1⎟⋅u[k, 0] - u[k - 1, 0]\n", + " 2 ⎜ hₓ 2 ⎟ \n", + " hₓ ⎝ hₓ ⎠ " + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "solution = Ω.solve(eqs[0].subs({i:0}), u[k, -1])[0]\n", + "# (-eqs[1]*2*h_x*gamma).subs({u[k, -1]: solution}).expand().collect([\n", + "# u[k, 0],\n", + "# u[k, 1],\n", + "# ])\n", + "(-eqs[1] * h_x * 2 * gamma_val).subs({u[k, -1]: solution}).expand().collect([\n", + " u[k, 0],\n", + " u[k, 1],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### $i=I$" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$- \\frac{2 D h_{t} {u}_{k,I - 1}}{h_{x}^{2}} + \\left(\\frac{2 D H h_{t}}{h_{x}} + \\frac{2 D h_{t}}{h_{x}^{2}} + 1\\right) {u}_{k,I} - {u}_{k - 1,I}$$" + ], + "text/plain": [ + " 2⋅D⋅hₜ⋅u[k, I - 1] ⎛2⋅D⋅H⋅hₜ 2⋅D⋅hₜ ⎞ \n", + "- ────────────────── + ⎜──────── + ────── + 1⎟⋅u[k, I] - u[k - 1, I]\n", + " 2 ⎜ hₓ 2 ⎟ \n", + " hₓ ⎝ hₓ ⎠ " + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "solution = Ω.solve(eqs[0].subs({i:I}), u[k, I+1])[0]\n", + "# (eqs[2] * 2 * h_x * gamma).subs({u[k, I+1]: solution}).expand().collect([\n", + "# u[k, I-1],\n", + "# u[k, I],\n", + "# ])\n", + "(eqs[2] * 2 * h_x * gamma_val).subs({u[k, I+1]: solution}).expand().collect([\n", + " u[k, I-1],\n", + " u[k, I],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## КН повышенного порядка аппроксимации" + ] + }, + { + "cell_type": "code", + "execution_count": 134, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\left [ - \\gamma {u}_{k - 1,i + 1} - \\gamma {u}_{k - 1,i - 1} + 2 \\gamma {u}_{k - 1,i} - \\gamma {u}_{k,i + 1} - \\gamma {u}_{k,i - 1} + 2 \\gamma {u}_{k,i} - 2 {u}_{k - 1,i} + 2 {u}_{k,i}, \\quad - H {u}_{k,0} + \\frac{- {u}_{k,-1} + {u}_{k,1}}{2 h_{x}}, \\quad H {u}_{k,I} + \\frac{{u}_{k,I + 1} - {u}_{k,I - 1}}{2 h_{x}}\\right ]$$" + ], + "text/plain": [ + "⎡ \n", + "⎢-γ⋅u[k - 1, i + 1] - γ⋅u[k - 1, i - 1] + 2⋅γ⋅u[k - 1, i] - γ⋅u[k, i + 1] - γ⋅\n", + "⎣ \n", + "\n", + " -u[k, -1] \n", + "u[k, i - 1] + 2⋅γ⋅u[k, i] - 2⋅u[k - 1, i] + 2⋅u[k, i], -H⋅u[k, 0] + ──────────\n", + " 2⋅\n", + "\n", + "+ u[k, 1] u[k, I + 1] - u[k, I - 1]⎤\n", + "─────────, H⋅u[k, I] + ─────────────────────────⎥\n", + "hₓ 2⋅hₓ ⎦" + ] + }, + "execution_count": 134, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "eqs = [\n", + " (u[k, i] - u[k - 1, i]) / h_t - D / 2 * (\n", + " (u[k-1, i + 1] - 2 * u[k-1, i] + u[k-1, i - 1]) +\n", + " (u[k, i + 1] - 2 * u[k, i] + u[k, i - 1])\n", + " ) / (h_x**2),\n", + " (u[k, 1] - u[k, -1]) / (2 * h_x) - H * u[k, 0],\n", + " (u[k, I+1] - u[k, I - 1]) / (2 * h_x) + H * u[k, I],\n", + "]\n", + "eqs[0] = (eqs[0] * 2 * h_t).expand().subs({gamma_val:gamma})\n", + "eqs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### $i=1,I-1$" + ] + }, + { + "cell_type": "code", + "execution_count": 135, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$\\gamma {u}_{k - 1,i + 1} + \\gamma {u}_{k - 1,i - 1} + \\gamma {u}_{k,i + 1} + \\gamma {u}_{k,i - 1} + \\left(- 2 \\gamma - 2\\right) {u}_{k,i} + \\left(- 2 \\gamma + 2\\right) {u}_{k - 1,i}$$" + ], + "text/plain": [ + "γ⋅u[k - 1, i + 1] + γ⋅u[k - 1, i - 1] + γ⋅u[k, i + 1] + γ⋅u[k, i - 1] + (-2⋅γ \n", + "- 2)⋅u[k, i] + (-2⋅γ + 2)⋅u[k - 1, i]" + ] + }, + "execution_count": 135, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(-eqs[0]).collect([\n", + " u[k, i-1],\n", + " u[k, i],\n", + " u[k, i+1],\n", + " u[k-1, i-1],\n", + " u[k-1, i],\n", + " u[k-1, i+1],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### $i=0$" + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$- \\gamma {u}_{k - 1,1} - \\gamma {u}_{k,1} + \\left(H \\gamma h_{x} + \\gamma - 1\\right) {u}_{k - 1,0} + \\left(H \\gamma h_{x} + \\gamma + 1\\right) {u}_{k,0}$$" + ], + "text/plain": [ + "-γ⋅u[k - 1, 1] - γ⋅u[k, 1] + (H⋅γ⋅hₓ + γ - 1)⋅u[k - 1, 0] + (H⋅γ⋅hₓ + γ + 1)⋅u\n", + "[k, 0]" + ] + }, + "execution_count": 150, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(eqs[0]/2).subs({i:0}).subs({\n", + " u[k, -1]: Ω.solve(eqs[1], u[k, -1])[0],\n", + " u[k-1, -1]: Ω.solve(eqs[1], u[k, -1])[0].subs({k:k-1}),\n", + "}).expand().collect([\n", + " u[k - 1, 0],\n", + " u[k - 1, 1],\n", + " u[k, 0],\n", + " u[k, 1],\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### $i=I$" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/latex": [ + "$$- \\gamma {u}_{k - 1,I - 1} - \\gamma {u}_{k,I - 1} + \\left(H \\gamma h_{x} + \\gamma - 1\\right) {u}_{k - 1,I} + \\left(H \\gamma h_{x} + \\gamma + 1\\right) {u}_{k,I}$$" + ], + "text/plain": [ + "-γ⋅u[k - 1, I - 1] - γ⋅u[k, I - 1] + (H⋅γ⋅hₓ + γ - 1)⋅u[k - 1, I] + (H⋅γ⋅hₓ + \n", + "γ + 1)⋅u[k, I]" + ] + }, + "execution_count": 151, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(eqs[0]/2).subs({i:I}).subs({\n", + " u[k, I+1]: Ω.solve(eqs[2], u[k, I+1])[0],\n", + " u[k-1, I+1]: Ω.solve(eqs[2], u[k, I+1])[0].subs({k:k-1}),\n", + "}).expand().collect([\n", + " u[k - 1, I],\n", + " u[k - 1, I+1],\n", + " u[k, I],\n", + " u[k, I+1],\n", + "])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/test_solvers.py b/test/test_solvers.py new file mode 100644 index 0000000..48b0adb --- /dev/null +++ b/test/test_solvers.py @@ -0,0 +1,31 @@ +import util +from solvers.crank_nicolson import solve_crank_nicolson, solve_crank_nicolson_improved +from solvers.explicit import solve_explicit +from solvers.implicit import solve_implicit, solve_implicit_improved +from solvers.theoretical import solve_theoretical +from util import Grid + +solvers = [ + solve_explicit, + solve_implicit, + solve_implicit_improved, + solve_crank_nicolson, + solve_crank_nicolson_improved, +] + + +def test_all(): + grid = Grid(16, 128) + + reference = solve_theoretical(grid) + + print() + print(grid) + + for solver in solvers: + solution = solver(grid) + + mse = util.mse(reference, solution) + mae = util.mae(reference, solution) + + print(f'{solver.__name__:30} {mse:.4e} {mae:.4e}') diff --git a/Катков.docx b/Катков.docx new file mode 100644 index 0000000..95353f2 Binary files /dev/null and b/Катков.docx differ diff --git a/Катков.pdf b/Катков.pdf new file mode 100644 index 0000000..55757fe Binary files /dev/null and b/Катков.pdf differ diff --git a/Лысый.docx b/Лысый.docx new file mode 100644 index 0000000..7340a43 Binary files /dev/null and b/Лысый.docx differ diff --git a/Методич. указания к к.р. по УМФ.2017 (1).doc b/Методич. указания к к.р. по УМФ.2017 (1).doc new file mode 100644 index 0000000..2b0c99e Binary files /dev/null and b/Методич. указания к к.р. по УМФ.2017 (1).doc differ diff --git a/Методич. указания к к.р. по УМФ.2017 (1).pdf b/Методич. указания к к.р. по УМФ.2017 (1).pdf new file mode 100644 index 0000000..9adf589 Binary files /dev/null and b/Методич. указания к к.р. по УМФ.2017 (1).pdf differ diff --git a/Нелысый.docx b/Нелысый.docx new file mode 100644 index 0000000..2e05721 Binary files /dev/null and b/Нелысый.docx differ diff --git a/Отчет_ЧММФ_Анурин_Гринина_Попов.docx b/Отчет_ЧММФ_Анурин_Гринина_Попов.docx new file mode 100644 index 0000000..98bf710 Binary files /dev/null and b/Отчет_ЧММФ_Анурин_Гринина_Попов.docx differ diff --git a/Отчет_ЧММФ_Анурин_Гринина_Попов.pdf b/Отчет_ЧММФ_Анурин_Гринина_Попов.pdf new file mode 100644 index 0000000..2ad212d Binary files /dev/null and b/Отчет_ЧММФ_Анурин_Гринина_Попов.pdf differ diff --git a/разностные схемы 2.ipynb b/разностные схемы 2.ipynb new file mode 100644 index 0000000..9c46eb2 --- /dev/null +++ b/разностные схемы 2.ipynb @@ -0,0 +1,906 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Populating the interactive namespace from numpy and matplotlib\n" + ] + } + ], + "source": [ + "%pylab inline" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas\n", + "import sympy as Ω\n", + "import matplotlib.pyplot as plt\n", + "import math\n", + "import pylab as p\n", + "import numpy as np\n", + "import decimal as d\n", + "from scipy.misc import derivative\n", + "import pickle\n", + "from tqdm import tqdm_notebook as tqdm\n", + "\n", + "from dataclasses import dataclass\n", + "\n", + "import scipy.sparse\n", + "import scipy.sparse.linalg\n", + "\n", + "import functools" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "Ω.init_printing()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "l_float = 20\n", + "T_float = 100\n", + "\n", + "D_float = 0.6\n", + "H_float = 4" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": {}, + "outputs": [], + "source": [ + "with open('/Users/abra/projects/study/7semestr/degtyarev/roots128.pickle', 'rb') as file:\n", + " roots128 = pickle.load(file)\n", + "\n", + "roots = roots128\n", + "\n", + "def u_elem128(x, t, alpha_n):\n", + " x = np.float128(x)\n", + " t = np.float128(t)\n", + " alpha_n = np.float128(alpha_n)\n", + " return -4*np.pi**2*(alpha_n*np.cos(alpha_n*x/10) + 40*np.sin(alpha_n*x/10))*(alpha_n*np.sin(2*alpha_n) - 40*np.cos(2*alpha_n) + 40)*np.exp(-3*alpha_n**2*t/500)/(5*(alpha_n**2 - np.pi**2)*(alpha_n**2*(4*alpha_n + np.sin(4*alpha_n)) - 80*alpha_n*(np.cos(4*alpha_n) - 1) + 6400*alpha_n - 1600*np.sin(4*alpha_n)))\n", + "\n", + "@functools.lru_cache(maxsize=100000)\n", + "def u128(x, t, root_n=len(roots)):\n", + " return sum(u_elem128(x, t, roots[:root_n]))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "@dataclass\n", + "class Grid:\n", + " I: int\n", + " K: int\n", + " \n", + " xs: ndarray\n", + " ts: ndarray\n", + " \n", + " h_x: float\n", + " h_t: float\n", + " \n", + " def __init__(self, I, K):\n", + " self.I = I\n", + " self.K = K\n", + "\n", + " self.xs = linspace(0, l_float, I + 1)\n", + " self.ts = linspace(0, T_float, K + 1)\n", + "\n", + " self.h_x = l_float / I\n", + " self.h_t = T_float / K\n", + " \n", + " self.gamma = D_float * self.h_t / (self.h_x ** 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def ug_mse(ug1, ug2):\n", + " return np.mean((ug1 - ug2) ** 2)\n", + "\n", + "def ug_mae(ug1, ug2):\n", + " return np.max(np.abs(ug1 - ug2))" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [], + "source": [ + "n = 5000\n", + "\n", + "np.random.seed(0)\n", + "\n", + "a = np.random.uniform(0, 0.1, size=n-1)\n", + "b = np.ones(n)\n", + "c = np.random.uniform(0, 0.1, size=n-1)\n", + "\n", + "z = np.random.uniform(0, 0.1, size=n)\n", + "\n", + "A = np.zeros((n, n))\n", + "\n", + "for i in range(n):\n", + " A[i, i] = b[i]\n", + " \n", + " if i > 0:\n", + " A[i, i - 1] = a[i - 1]\n", + " \n", + " if i < n - 1:\n", + " A[i, i + 1] = c[i]" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.52 s ± 78.3 ms per loop (mean ± std. dev. of 5 runs, 5 loops each)\n" + ] + } + ], + "source": [ + "%%timeit -n 5 -r 5\n", + "np.linalg.solve(A, z)" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [], + "source": [ + "A_sp = scipy.sparse.diags([a, b, c], [-1, 0, 1], format='csc')" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.1 ms ± 430 µs per loop (mean ± std. dev. of 5 runs, 5 loops each)\n" + ] + } + ], + "source": [ + "%%timeit -n 5 -r 5\n", + "scipy.sparse.linalg.spsolve(A_sp, z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## теория" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def calc_theoretical(grid):\n", + " ug = zeros((grid.K + 1, grid.I + 1), dtype=float)\n", + " \n", + " for k, t in enumerate(grid.ts):\n", + " for i, x in enumerate(grid.xs):\n", + " ug[k, i] = u128(x, t, 100)\n", + " \n", + " return ug" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "58.89331758385291\n" + ] + } + ], + "source": [ + "grid = Grid(10, 50)\n", + "print(sum(calc_theoretical(grid)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## простейшая явная схема" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def calc_explicit(grid):\n", + " if grid.gamma > 1/2:\n", + " raise Exception('Bad gamma!')\n", + " \n", + " ug = zeros((grid.K + 1, grid.I + 1), dtype=float)\n", + "\n", + " ug[0, :] = sin(np.pi * grid.xs / l_float) ** 2 * 4 / 10\n", + "\n", + " for k in range(1, grid.K + 1):\n", + " # middle\n", + " ug[k, 1 : grid.I] = (\n", + " grid.gamma * ug[k - 1, 0 : grid.I - 1] +\n", + " (-2 * grid.gamma + 1) * ug[k - 1, 1 : grid.I] + \n", + " grid.gamma * ug[k - 1, 2 : grid.I + 1]\n", + " )\n", + "\n", + " # left\n", + " ug[k, 0] = ug[k, 1] / (H_float * grid.h_x + 1)\n", + "\n", + " # right\n", + " ug[k, grid.I] = ug[k, grid.I - 1] / (H_float * grid.h_x + 1)\n", + " \n", + " return ug" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "58.72948448630509\n", + "4.3733803061715146e-07\n" + ] + } + ], + "source": [ + "grid = Grid(10, 50)\n", + "ug = calc_explicit(grid)\n", + "print(sum(ug))\n", + "print(ug_mse(ug, calc_theoretical(grid)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## простейшая неявная схема" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [], + "source": [ + "def calc_implicit(grid):\n", + " ug = zeros((grid.K + 1, grid.I + 1), dtype=float)\n", + "\n", + " ug[0, :] = sin(np.pi * grid.xs / l_float) ** 2 * 4 / 10\n", + "\n", + " for k in range(1, grid.K + 1):\n", + " diags = {\n", + " -1: np.zeros(grid.I + 1, dtype=float),\n", + " 0: np.zeros(grid.I + 1, dtype=float),\n", + " +1: np.zeros(grid.I + 1, dtype=float),\n", + " }\n", + " b = np.zeros(grid.I + 1, dtype=float)\n", + "\n", + " # left\n", + " diags[ 0][0] = H_float + 1 / grid.h_x\n", + " diags[+1][0] = -1 / grid.h_x\n", + "\n", + " # middle\n", + " for i in range(1, grid.I):\n", + " diags[-1][i] = grid.gamma\n", + " diags[ 0][i] = - 2 * grid.gamma - 1\n", + " diags[+1][i] = grid.gamma\n", + " b[i] = -ug[k - 1, i]\n", + "\n", + " # right\n", + " diags[ 0][grid.I] = H_float + 1 / grid.h_x\n", + " diags[-1][grid.I] = -1 / grid.h_x\n", + "\n", + " A = scipy.sparse.diags([\n", + " diags[-1][1:], \n", + " diags[ 0], \n", + " diags[+1][:-1],\n", + " ], [-1, 0, 1], format='csc')\n", + " \n", + " ug[k, :] = scipy.sparse.linalg.spsolve(A, b)\n", + " \n", + " return ug" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "59.49556361037571\n", + "4.006492537092588e-06\n" + ] + } + ], + "source": [ + "grid = Grid(10, 50)\n", + "ug = calc_implicit(grid)\n", + "print(sum(ug))\n", + "print(ug_mse(ug, calc_theoretical(grid)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## схема Кранка-Николсон" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [], + "source": [ + "def calc_kn(grid):\n", + " ug = zeros((grid.K + 1, grid.I + 1), dtype=float)\n", + "\n", + " ug[0, :] = sin(np.pi * grid.xs / l_float) ** 2 * 4 / 10\n", + "\n", + " for k in range(1, grid.K + 1):\n", + " diags = {\n", + " -1: np.zeros(grid.I + 1, dtype=float),\n", + " 0: np.zeros(grid.I + 1, dtype=float),\n", + " +1: np.zeros(grid.I + 1, dtype=float),\n", + " }\n", + " b = np.zeros(grid.I + 1, dtype=float)\n", + "\n", + " # left\n", + " diags[ 0][0] = H_float + 1 / grid.h_x\n", + " diags[+1][0] = -1 / grid.h_x\n", + "\n", + " # middle\n", + " for i in range(1, grid.I):\n", + " diags[-1][i] = grid.gamma\n", + " diags[ 0][i] = - 2 * grid.gamma - 2\n", + " diags[+1][i] = grid.gamma\n", + " b[i] = -(\n", + " ug[k - 1][i - 1] * grid.gamma +\n", + " ug[k - 1][i] * (-2 * grid.gamma + 2) +\n", + " ug[k - 1][i + 1] * grid.gamma\n", + " )\n", + "\n", + " # right\n", + " diags[ 0][grid.I] = H_float + 1 / grid.h_x\n", + " diags[-1][grid.I] = -1 / grid.h_x\n", + "\n", + " A = scipy.sparse.diags([\n", + " diags[-1][1:], \n", + " diags[ 0], \n", + " diags[+1][:-1],\n", + " ], [-1, 0, 1], format='csc')\n", + " \n", + " ug[k, :] = scipy.sparse.linalg.spsolve(A, b)\n", + " \n", + " return ug" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.048762671501371764\n", + "5.115545125775158e-07\n" + ] + } + ], + "source": [ + "grid = Grid(10, 50)\n", + "ug = calc_kn(grid)\n", + "print(mean(ug[-1]))\n", + "print(ug_mse(ug, calc_theoretical(grid)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## простейшая неявная схема повышенного порядка аппроксимации" + ] + }, + { + "cell_type": "code", + "execution_count": 174, + "metadata": {}, + "outputs": [], + "source": [ + "def calc_implicit_improved(grid):\n", + " ug = zeros((grid.K + 1, grid.I + 1), dtype=float)\n", + "\n", + " ug[0, :] = sin(np.pi * grid.xs / l_float) ** 2 * 4 / 10\n", + "\n", + " for k in range(1, grid.K + 1):\n", + " diags = {\n", + " -1: np.zeros(grid.I + 1, dtype=float),\n", + " 0: np.zeros(grid.I + 1, dtype=float),\n", + " +1: np.zeros(grid.I + 1, dtype=float),\n", + " }\n", + " b = np.zeros(grid.I + 1, dtype=float)\n", + "\n", + " # left\n", + " diags[ 0][0] = (\n", + " 2 * H_float * grid.gamma * grid.h_x + \n", + " 2 * grid.gamma + \n", + " 1\n", + " )\n", + " diags[+1][0] = - 2 * grid.gamma\n", + " b[0] = ug[k - 1, 0]\n", + "\n", + " # middle\n", + " for i in range(1, grid.I):\n", + " diags[-1][i] = grid.gamma\n", + " diags[ 0][i] = - 2 * grid.gamma - 1\n", + " diags[+1][i] = grid.gamma\n", + " b[i] = -ug[k - 1, i]\n", + "\n", + " # right\n", + " diags[ 0][grid.I] = (\n", + " 2 * H_float * grid.gamma * grid.h_x + \n", + " 2 * grid.gamma + \n", + " 1\n", + " )\n", + " diags[-1][grid.I] = - 2 * grid.gamma\n", + " b[grid.I] = ug[k - 1, grid.I]\n", + "\n", + " A = scipy.sparse.diags([\n", + " diags[-1][1:], \n", + " diags[ 0], \n", + " diags[+1][:-1],\n", + " ], [-1, 0, 1], format='csc')\n", + " \n", + " ug[k, :] = scipy.sparse.linalg.spsolve(A, b)\n", + " \n", + " return ug" + ] + }, + { + "cell_type": "code", + "execution_count": 177, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "59.486724613775095\n", + "4.014426575945732e-06\n" + ] + } + ], + "source": [ + "grid = Grid(10, 50)\n", + "ug = calc_implicit_improved(grid)\n", + "print(sum(ug))\n", + "print(ug_mse(ug, calc_theoretical(grid)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Кранк-Николсон повышенного порядка аппроксимации" + ] + }, + { + "cell_type": "code", + "execution_count": 174, + "metadata": {}, + "outputs": [], + "source": [ + "def calc_kn_improved(grid):\n", + " ug = zeros((grid.K + 1, grid.I + 1), dtype=float)\n", + "\n", + " ug[0, :] = sin(np.pi * grid.xs / l_float) ** 2 * 4 / 10\n", + "\n", + " for k in range(1, grid.K + 1):\n", + " diags = {\n", + " -1: np.zeros(grid.I + 1, dtype=float),\n", + " 0: np.zeros(grid.I + 1, dtype=float),\n", + " +1: np.zeros(grid.I + 1, dtype=float),\n", + " }\n", + " b = np.zeros(grid.I + 1, dtype=float)\n", + "\n", + " # left\n", + " #diags[ 0][0] = H_float + 1 / grid.h_x\n", + " #diags[+1][0] = -1 / grid.h_x\n", + " \n", + " diags[ 0][0] = (\n", + " 2 * H_float * grid.gamma * grid.h_x + \n", + " 2 * grid.gamma + \n", + " 1\n", + " )\n", + " diags[+1][0] = - 2 * grid.gamma\n", + " b[0] = ug[k - 1, 0]\n", + "\n", + " # middle\n", + " for i in range(1, grid.I):\n", + " diags[-1][i] = grid.gamma\n", + " diags[ 0][i] = - 2 * grid.gamma - 2\n", + " diags[+1][i] = grid.gamma\n", + " b[i] = -(\n", + " ug[k - 1][i - 1] * grid.gamma +\n", + " ug[k - 1][i] * (-2 * grid.gamma + 2) +\n", + " ug[k - 1][i + 1] * grid.gamma\n", + " )\n", + "\n", + " # right\n", + " diags[ 0][grid.I] = H_float + 1 / grid.h_x\n", + " diags[-1][grid.I] = -1 / grid.h_x\n", + "\n", + " A = scipy.sparse.diags([\n", + " diags[-1][1:], \n", + " diags[ 0], \n", + " diags[+1][:-1],\n", + " ], [-1, 0, 1], format='csc')\n", + " \n", + " ug[k, :] = scipy.sparse.linalg.spsolve(A, b)\n", + " \n", + " return ug" + ] + }, + { + "cell_type": "code", + "execution_count": 177, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "59.486724613775095\n", + "4.014426575945732e-06\n" + ] + } + ], + "source": [ + "grid = Grid(10, 50)\n", + "ug = calc_kn_improved(grid)\n", + "print(sum(ug))\n", + "print(ug_mse(ug, calc_theoretical(grid)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## сравнение" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAO4AAAAPBAMAAAAR2O42AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAMpndu3bvImbNiRBUq0Qb3U6NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADlklEQVQ4Eb2TT4hbVRTGf8nkz5u8JBN0J8jEwT906rSDFUrFYlDRjdqhIGqlTIRS0Rlq6KLKbPo2yuCmEV0IVYnakTEgBksLFiRv5a4kDnQYhdKg6LbS/zNJTc8596UdU9deeCffO/d835dz3r0A98gDC/UXiO2erNcNuXBq3zbwJz8skK6fCOGH5S+lsr6voAS4d6VerxkafT32qAENqpdZ0srhZVK3WY/rdrpIK/D6/f5NQxYokgsZDf2dHCZ7Az7jZIUfO/Eq/NyAY1LeJjsHqX6/JiKaBNHzv2CLwqFlUo4FyQO6m+wxNh2vQNuQhWxAusoH8C2zIZfxymSqPE2i5K9cEItHIMdPU10Y/e4VMbOk6SWKPDvkqa8mZSx5ee8TTeUP0axmZEAFQ+61hD/Ni9Bq/NXx10lIc938dS1nVnxrINNMim/OcpY0vYvSwH8sk6oZS9jmK1WtQMKf8jjUCvJXGpmAm3AxROc81ibfS5S1wlmQn7nbV/Wes5q7QiSlLLxK5Os/oXUleQxpuHBjGf+S+ErhyRrNIvmrYx8tyWGLfBOCrN/FvYUoaXrr9+3twJmXZaab1kBKWZzC+aa/3ipv0h+GLGT6x0lvwHiNhccaHK0R22h+Sioc+C7jfBON9D8Cdfiq568HzJPfyYIk76xICmXJRxrM+ZsONK1KERLO/nGtk5Z+xZfMIY4W1bdLXE6wWuD/LUH7lfWMPO6ji2+/wcONI6H/gG0NQiRlrGzhtm9K5F6zGkWk5rw2s3OD4XCw4eY8jSe9mW+yKnWR7/aKJZ3eZblkndX3X7U/9/EOWbsK8jfdJzPWGZxvukKiZ3fPkIVUhVhPz1UrfBf2hHKusr2RKp5cZfMdKUW+v8L3HUs6vV3iGwhxaJkUxjp7/vy1c7I91lVfX3YMWdChr+lFPNaQwe0JEyW8bq58p99mWyq037dgu/Qmf8bprWq/G0OuOCmMJXsHdD9VYuQ6MZmEIRcq8Lxe9i1a81TFKxOvxuT7lqN+x4vCVF/5lRbdELR2XL4vb8ueJDctk8JYkr0i5w8voDVDVnwNWcgfx5thJPTfYJHsVXiS0wV+43QYWbSKQlffw3hvCrThix65mj8vZ8X/9z1yUhgLTvTX2A2/T7wkV2he2IYs3D+5TU7D0v4C+YkHO3ohf5GDPSFh6p3PAzgSQnx1fY305IqM2SVVj6+mCiQfWhS1zcukjLU5+3/iW7ckZCmz5Ei9AAAAAElFTkSuQmCC\n", + "text/latex": [ + "$$4.3733803061715146e-07$$" + ], + "text/plain": [ + "4.3733803061715146e-07" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ug_mse(calc_theoretical(grid), calc_explicit(grid))" + ] + }, + { + "cell_type": "code", + "execution_count": 169, + "metadata": {}, + "outputs": [], + "source": [ + "def print_comparison(Is, Ks, E, i_p, k_p, i_d, k_d):\n", + " if (\n", + " not 0 <= i_p < len(Is) or\n", + " not 0 <= k_p < len(Ks) or\n", + " not 0 <= i_p + i_d < len(Is) or\n", + " not 0 <= k_p + k_d < len(Ks) or\n", + " E[k_p, i_p] < 0 or\n", + " E[k_p + k_d, i_p + i_d] < 0\n", + " ):\n", + " return\n", + " \n", + " error_ratio = E[k_p, i_p] / E[k_p + k_d, i_p + i_d]\n", + " \n", + " I1 = Is[i_p]\n", + " I2 = Is[i_p + i_d]\n", + " K1 = Ks[k_p]\n", + " K2 = Ks[k_p + k_d]\n", + " \n", + " print(f'h_x x{I2//I1} h_t x{K2//K1} @ ({I1:5},{K1:5}): {error_ratio}')" + ] + }, + { + "cell_type": "code", + "execution_count": 170, + "metadata": {}, + "outputs": [], + "source": [ + "def compare_errors(Is, Ks, calc_function):\n", + " E = np.zeros((len(Ks), len(Is)))\n", + "\n", + " for k_p in range(len(Ks)):\n", + " for i_p in range(len(Is)):\n", + " grid = Grid(Is[i_p], Ks[k_p])\n", + "\n", + " try:\n", + " error = ug_mae(calc_function(grid), calc_theoretical(grid))\n", + " except:\n", + " error = -1\n", + "\n", + " E[k_p, i_p] = error\n", + " \n", + " for k_p in range(len(Ks)):\n", + " for i_p in range(len(Is)):\n", + " print_comparison(Is, Ks, E, i_p, k_p, +1, +1)\n", + " \n", + " for k_p in range(len(Ks)):\n", + " for i_p in range(len(Is)):\n", + " print_comparison(Is, Ks, E, i_p, k_p, +2, +1)\n", + " \n", + " for k_p in range(len(Ks)):\n", + " for i_p in range(len(Is)):\n", + " print_comparison(Is, Ks, E, i_p, k_p, +1, +2)" + ] + }, + { + "cell_type": "code", + "execution_count": 171, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "h_x x2 h_t x4 @ ( 16, 256): 1.919077767270527\n" + ] + } + ], + "source": [ + "compare_errors([16, 32, 64, 128, 256], [256, 1024], calc_explicit)" + ] + }, + { + "cell_type": "code", + "execution_count": 172, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "h_x x2 h_t x2 @ ( 16, 16): 1.8945839194805507\n", + "h_x x2 h_t x2 @ ( 32, 16): 1.8480652483857702\n", + "h_x x2 h_t x2 @ ( 64, 16): 1.825718428756318\n", + "h_x x2 h_t x2 @ ( 128, 16): 1.8200879583854386\n", + "h_x x2 h_t x2 @ ( 16, 32): 2.011003900865954\n", + "h_x x2 h_t x2 @ ( 32, 32): 1.8852164156444766\n", + "h_x x2 h_t x2 @ ( 64, 32): 1.8445734893796497\n", + "h_x x2 h_t x2 @ ( 128, 32): 1.8438755692851074\n", + "h_x x2 h_t x2 @ ( 16, 64): 2.17619657916294\n", + "h_x x2 h_t x2 @ ( 32, 64): 1.9562383707853712\n", + "h_x x2 h_t x2 @ ( 64, 64): 1.912181287104185\n", + "h_x x2 h_t x2 @ ( 128, 64): 1.9058730801460957\n", + "h_x x2 h_t x2 @ ( 16, 128): 2.3986401861806734\n", + "h_x x2 h_t x2 @ ( 32, 128): 2.066009495516749\n", + "h_x x2 h_t x2 @ ( 64, 128): 1.9741429057474853\n", + "h_x x2 h_t x2 @ ( 128, 128): 1.955899186659026\n", + "h_x x4 h_t x2 @ ( 16, 16): 1.9431575629889533\n", + "h_x x4 h_t x2 @ ( 32, 16): 1.8496006164556726\n", + "h_x x4 h_t x2 @ ( 64, 16): 1.8261475842007147\n", + "h_x x4 h_t x2 @ ( 16, 32): 2.0776417503976705\n", + "h_x x4 h_t x2 @ ( 32, 32): 1.8918649575362794\n", + "h_x x4 h_t x2 @ ( 64, 32): 1.845407456579902\n", + "h_x x4 h_t x2 @ ( 16, 64): 2.326489502477712\n", + "h_x x4 h_t x2 @ ( 32, 64): 1.9755444903443895\n", + "h_x x4 h_t x2 @ ( 64, 64): 1.9125944713395193\n", + "h_x x4 h_t x2 @ ( 16, 128): 2.8326076010600714\n", + "h_x x4 h_t x2 @ ( 32, 128): 2.1104815578650395\n", + "h_x x4 h_t x2 @ ( 64, 128): 1.9752019588093679\n", + "h_x x2 h_t x4 @ ( 16, 16): 3.45714271998841\n", + "h_x x2 h_t x4 @ ( 32, 16): 3.396912364589268\n", + "h_x x2 h_t x4 @ ( 64, 16): 3.3648762818042726\n", + "h_x x2 h_t x4 @ ( 128, 16): 3.3552270369444783\n", + "h_x x2 h_t x4 @ ( 16, 32): 3.6798635241236157\n", + "h_x x2 h_t x4 @ ( 32, 32): 3.569646703206942\n", + "h_x x2 h_t x4 @ ( 64, 32): 3.514763487476464\n", + "h_x x2 h_t x4 @ ( 128, 32): 3.512604694405925\n", + "h_x x2 h_t x4 @ ( 16, 64): 3.8072301037478553\n", + "h_x x2 h_t x4 @ ( 32, 64): 3.780516278348026\n", + "h_x x2 h_t x4 @ ( 64, 64): 3.7380285131624063\n", + "h_x x2 h_t x4 @ ( 128, 64): 3.726890300676519\n" + ] + } + ], + "source": [ + "compare_errors([16, 32, 64, 128, 256], [16, 32, 64, 128, 256], calc_implicit)" + ] + }, + { + "cell_type": "code", + "execution_count": 173, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "h_x x2 h_t x2 @ ( 16, 16): 1.7867407245342732\n", + "h_x x2 h_t x2 @ ( 32, 16): 2.0659339289789247\n", + "h_x x2 h_t x2 @ ( 64, 16): 2.206577164218172\n", + "h_x x2 h_t x2 @ ( 128, 16): 2.205398898130605\n", + "h_x x2 h_t x2 @ ( 16, 32): 1.0260466758467883\n", + "h_x x2 h_t x2 @ ( 32, 32): 1.985994321847054\n", + "h_x x2 h_t x2 @ ( 64, 32): 2.0974055723617107\n", + "h_x x2 h_t x2 @ ( 128, 32): 2.1318052621473274\n", + "h_x x2 h_t x2 @ ( 16, 64): 1.8854175495471748\n", + "h_x x2 h_t x2 @ ( 32, 64): 1.5501374544674071\n", + "h_x x2 h_t x2 @ ( 64, 64): 2.0605293935478826\n", + "h_x x2 h_t x2 @ ( 128, 64): 2.1241455078974423\n", + "h_x x2 h_t x2 @ ( 16, 128): 2.2073516657031678\n", + "h_x x2 h_t x2 @ ( 32, 128): 1.8202146022973351\n", + "h_x x2 h_t x2 @ ( 64, 128): 1.8615590435162546\n", + "h_x x2 h_t x2 @ ( 128, 128): 2.093178235555532\n", + "h_x x4 h_t x2 @ ( 16, 16): 1.5416112730228488\n", + "h_x x4 h_t x2 @ ( 32, 16): 1.9411758005230835\n", + "h_x x4 h_t x2 @ ( 64, 16): 2.132375626592411\n", + "h_x x4 h_t x2 @ ( 16, 32): 0.672923482269376\n", + "h_x x4 h_t x2 @ ( 32, 32): 1.8096548816821525\n", + "h_x x4 h_t x2 @ ( 64, 32): 2.0030692793517577\n", + "h_x x4 h_t x2 @ ( 16, 64): 2.09685316770308\n", + "h_x x4 h_t x2 @ ( 32, 64): 1.3513796667001667\n", + "h_x x4 h_t x2 @ ( 64, 64): 1.9355394149338634\n", + "h_x x4 h_t x2 @ ( 16, 128): 5.089679627450866\n", + "h_x x4 h_t x2 @ ( 32, 128): 2.07031910687416\n", + "h_x x4 h_t x2 @ ( 64, 128): 1.8247920519286784\n", + "h_x x2 h_t x4 @ ( 16, 16): 5.410544492760973\n", + "h_x x2 h_t x4 @ ( 32, 16): 4.755334696107873\n", + "h_x x2 h_t x4 @ ( 64, 16): 4.925531450048806\n", + "h_x x2 h_t x4 @ ( 128, 16): 4.865081194253896\n", + "h_x x2 h_t x4 @ ( 16, 32): 1.4301343984858494\n", + "h_x x2 h_t x4 @ ( 32, 32): 4.6940709147810455\n", + "h_x x2 h_t x4 @ ( 64, 32): 4.742894620222057\n", + "h_x x2 h_t x4 @ ( 128, 32): 4.7415271368204355\n", + "h_x x2 h_t x4 @ ( 16, 64): 1.4883710757235502\n", + "h_x x2 h_t x4 @ ( 32, 64): 2.537069293873301\n", + "h_x x2 h_t x4 @ ( 64, 64): 4.399957273891053\n", + "h_x x2 h_t x4 @ ( 128, 64): 4.733335280216436\n" + ] + } + ], + "source": [ + "compare_errors([16, 32, 64, 128, 256], [16, 32, 64, 128, 256], calc_kn)" + ] + }, + { + "cell_type": "code", + "execution_count": 181, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "h_x x2 h_t x2 @ ( 32, 128): 2.038390823677269\n", + "h_x x2 h_t x2 @ ( 64, 128): 1.9736276882133699\n", + "h_x x2 h_t x2 @ ( 32, 256): 2.1614872398503246\n", + "h_x x2 h_t x2 @ ( 64, 256): 2.025328231523804\n", + "h_x x2 h_t x2 @ ( 32, 512): 2.373745419372439\n", + "h_x x2 h_t x2 @ ( 64, 512): 2.0878950429120877\n", + "h_x x2 h_t x2 @ ( 32, 1024): 2.713172301556474\n", + "h_x x2 h_t x2 @ ( 64, 1024): 2.185936854335897\n", + "h_x x4 h_t x2 @ ( 32, 128): 2.1195416132190292\n", + "h_x x4 h_t x2 @ ( 32, 256): 2.330981592342115\n", + "h_x x4 h_t x2 @ ( 32, 512): 2.7365187229137757\n", + "h_x x4 h_t x2 @ ( 32, 1024): 3.543382713251337\n", + "h_x x2 h_t x4 @ ( 32, 128): 3.8282183811233788\n", + "h_x x2 h_t x4 @ ( 64, 128): 3.8442015881699336\n", + "h_x x2 h_t x4 @ ( 32, 256): 3.9146871029344097\n", + "h_x x2 h_t x4 @ ( 64, 256): 3.921190229218736\n", + "h_x x2 h_t x4 @ ( 32, 512): 3.973114349424527\n", + "h_x x2 h_t x4 @ ( 64, 512): 3.958967998390918\n" + ] + } + ], + "source": [ + "compare_errors([32, 64, 128], [128, 256, 512, 1024, 2048], calc_implicit_improved)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/разностные схемы.docx b/разностные схемы.docx new file mode 100644 index 0000000..6196852 Binary files /dev/null and b/разностные схемы.docx differ diff --git a/разностные схемы.pdf b/разностные схемы.pdf new file mode 100644 index 0000000..c23e998 Binary files /dev/null and b/разностные схемы.pdf differ