├── .github └── workflows │ └── matlab.yml ├── .gitignore ├── .gitmodules ├── .readthedocs.yaml ├── CITATION.cff ├── LICENSE.md ├── README.md ├── chunkie ├── +chnk │ ├── +arcparam │ │ ├── eval.m │ │ └── init.m │ ├── +axissymhelm2d │ │ ├── asym_helm_data.mat │ │ ├── asym_helm_data2.mat │ │ ├── dalph.m │ │ ├── der_ak_to_grad.m │ │ ├── div_by_kap.m │ │ ├── green.m │ │ ├── green_neu_all.m │ │ ├── helm_axi_all.m │ │ ├── helm_axi_close_table.m │ │ ├── helm_axi_smooth.m │ │ ├── kern.m │ │ ├── load_asym_tables.m │ │ └── load_asym_tables_sub.m │ ├── +curves │ │ ├── bymode.m │ │ ├── fpara.m │ │ ├── fsine.m │ │ └── linefunc.m │ ├── +demo │ │ └── barbell.m │ ├── +elast2d │ │ └── kern.m │ ├── +flam │ │ ├── kernbyindex.m │ │ ├── kernbyindexr.m │ │ ├── nproxy_square.m │ │ ├── proxy_circ_pts.m │ │ ├── proxy_rect_pts.m │ │ ├── proxy_square_pts.m │ │ ├── proxyfun.m │ │ └── proxyfunr.m │ ├── +helm1d │ │ ├── green.m │ │ ├── kern.m │ │ └── sweep.m │ ├── +helm2d │ │ ├── besseldiff_etc_pscoefs.m │ │ ├── even_pseval.m │ │ ├── fmm.m │ │ ├── green.m │ │ ├── helmdiffgreen.m │ │ ├── kern.m │ │ └── transmission_helper.m │ ├── +helm2dquas │ │ ├── green.m │ │ ├── kern.m │ │ └── latticecoefs.m │ ├── +intchunk │ │ ├── fcoefs.m │ │ ├── fhandle.m │ │ └── kerncoefs.m │ ├── +lap2d │ │ ├── fmm.m │ │ ├── green.m │ │ └── kern.m │ ├── +quadadap │ │ └── buildmat.m │ ├── +quadba │ │ ├── buildmat.m │ │ ├── buildmattd.m │ │ ├── getlogquad.m │ │ ├── logavail.m │ │ └── logwhts.mat │ ├── +quadggq │ │ ├── buildmat.m │ │ ├── buildmattd.m │ │ ├── diagbuildmat.m │ │ ├── gethqsuppquad.m │ │ ├── getlogquad.m │ │ ├── ggqnear.m │ │ ├── ggqnear16.m │ │ ├── ggqnear20.m │ │ ├── ggqnear24.m │ │ ├── ggqnear30.m │ │ ├── ggqnear40.m │ │ ├── ggqnear60.m │ │ ├── ggqself_nnode001_npoly002.m │ │ ├── ggqself_nnode001_npoly003.m │ │ ├── ggqself_nnode002_npoly004.m │ │ ├── ggqself_nnode002_npoly006.m │ │ ├── ggqself_nnode003_npoly006.m │ │ ├── ggqself_nnode003_npoly009.m │ │ ├── ggqself_nnode004_npoly008.m │ │ ├── ggqself_nnode004_npoly012.m │ │ ├── ggqself_nnode005_npoly010.m │ │ ├── ggqself_nnode005_npoly015.m │ │ ├── ggqself_nnode006_npoly012.m │ │ ├── ggqself_nnode006_npoly018.m │ │ ├── ggqself_nnode007_npoly014.m │ │ ├── ggqself_nnode007_npoly021.m │ │ ├── ggqself_nnode008_npoly016.m │ │ ├── ggqself_nnode008_npoly024.m │ │ ├── ggqself_nnode009_npoly018.m │ │ ├── ggqself_nnode009_npoly027.m │ │ ├── ggqself_nnode010_npoly020.m │ │ ├── ggqself_nnode010_npoly030.m │ │ ├── ggqself_nnode011_npoly022.m │ │ ├── ggqself_nnode011_npoly033.m │ │ ├── ggqself_nnode012_npoly024.m │ │ ├── ggqself_nnode012_npoly036.m │ │ ├── ggqself_nnode013_npoly026.m │ │ ├── ggqself_nnode013_npoly039.m │ │ ├── ggqself_nnode014_npoly028.m │ │ ├── ggqself_nnode014_npoly042.m │ │ ├── ggqself_nnode015_npoly030.m │ │ ├── ggqself_nnode015_npoly045.m │ │ ├── ggqself_nnode016_npoly032.m │ │ ├── ggqself_nnode016_npoly048.m │ │ ├── ggqself_nnode020_npoly040.m │ │ ├── ggqself_nnode020_npoly060.m │ │ ├── ggqself_nnode024_npoly048.m │ │ ├── ggqself_nnode024_npoly072.m │ │ ├── ggqself_nnode028_npoly056.m │ │ ├── ggqself_nnode028_npoly084.m │ │ ├── ggqself_nnode032_npoly064.m │ │ ├── ggqself_nnode032_npoly096.m │ │ ├── ggqself_nnode036_npoly072.m │ │ ├── ggqself_nnode040_npoly080.m │ │ ├── hqsupp_nnode001_npoly002.m │ │ ├── hqsupp_nnode002_npoly004.m │ │ ├── hqsupp_nnode003_npoly006.m │ │ ├── hqsupp_nnode004_npoly008.m │ │ ├── hqsupp_nnode005_npoly010.m │ │ ├── hqsupp_nnode006_npoly012.m │ │ ├── hqsupp_nnode008_npoly016.m │ │ ├── hqsupp_nnode010_npoly020.m │ │ ├── hqsupp_nnode012_npoly024.m │ │ ├── hqsupp_nnode016_npoly032.m │ │ ├── hqsupp_nnode020_npoly040.m │ │ ├── hsupp_nnode001_npoly002.m │ │ ├── hsupp_nnode002_npoly004.m │ │ ├── hsupp_nnode003_npoly006.m │ │ ├── hsupp_nnode004_npoly008.m │ │ ├── hsupp_nnode005_npoly010.m │ │ ├── hsupp_nnode006_npoly012.m │ │ ├── hsupp_nnode008_npoly016.m │ │ ├── hsupp_nnode010_npoly020.m │ │ ├── hsupp_nnode012_npoly024.m │ │ ├── hsupp_nnode016_npoly032.m │ │ ├── hsupp_nnode020_npoly040.m │ │ ├── logavail.m │ │ ├── logwhts.mat │ │ ├── nearbuildmat.m │ │ ├── setup.m │ │ └── setuplogquad.m │ ├── +quadnative │ │ └── buildmat.m │ ├── +rcip │ │ ├── IPinit.m │ │ ├── Pbcinit.m │ │ ├── Rcompchunk.m │ │ ├── SchurBana.m │ │ ├── chunkerfunclocal.m │ │ ├── rhohatInterp.m │ │ ├── setup.m │ │ └── shiftedlegbasismats.m │ ├── +smoother │ │ ├── expeval.m │ │ ├── get_mesh.m │ │ ├── get_sigs.m │ │ ├── get_umesh.m │ │ ├── gpsi_all.m │ │ ├── gpsi_loc.m │ │ ├── green.m │ │ ├── merge.m │ │ ├── newt_step.m │ │ ├── psi_eval.m │ │ ├── smooth.m │ │ ├── smooth_curve.m │ │ ├── smooth_curve2.m │ │ └── smooth_curve3.m │ ├── +spcl │ │ └── absconvgauss.m │ ├── +stok2d │ │ ├── fmm.m │ │ └── kern.m │ ├── adapgausskerneval.m │ ├── adapgausswts.m │ ├── chunk_nearparam.m │ ├── chunkerkerneval_smooth.m │ ├── curvature2d.m │ ├── ellipse_oversample.m │ ├── flagself.m │ ├── funcuni.m │ ├── normal2d.m │ ├── perp.m │ └── pquadwts.m ├── +lege │ ├── adapgauss.m │ ├── barywts.m │ ├── bernstein_ellipse.m │ ├── dermat.m │ ├── derpol.m │ ├── exev.m │ ├── exps.m │ ├── intmat.m │ ├── intpol.m │ ├── matrin.m │ ├── pol.m │ ├── pols.m │ ├── polsum.m │ ├── rts.m │ ├── rts_stab.m │ └── tayl.m ├── @chunker │ ├── arclengthdens.m │ ├── arclengthfun.m │ ├── arcresample.m │ ├── area.m │ ├── centroids.m │ ├── checkadjinfo.m │ ├── chunkends.m │ ├── chunker.m │ ├── chunkerpoints.m │ ├── chunklen.m │ ├── datares.m │ ├── diffmat.m │ ├── ellipses.m │ ├── exps.m │ ├── flagnear.m │ ├── flagnear_rectangle.m │ ├── flagnear_rectangle_grid.m │ ├── intmat.m │ ├── max.m │ ├── merge.m │ ├── min.m │ ├── move.m │ ├── mtimes.m │ ├── nearest.m │ ├── normals.m │ ├── normonesmat.m │ ├── onesmat.m │ ├── plot.m │ ├── plot3.m │ ├── plus.m │ ├── quiver.m │ ├── refine.m │ ├── reflect.m │ ├── reverse.m │ ├── rotate.m │ ├── scatter.m │ ├── signed_curvature.m │ ├── sort.m │ ├── sortinfo.m │ ├── split.m │ ├── tangents.m │ ├── taus.m │ ├── upsample.m │ ├── weights.m │ └── whts.m ├── @chunkerpref │ └── chunkerpref.m ├── @chunkgraph │ ├── balance.m │ ├── build_v2emat.m │ ├── chunkgraph.m │ ├── datares.m │ ├── find_edge_regions.m │ ├── findregions.m │ ├── findunbounded.m │ ├── flagnear.m │ ├── flagnear_rectangle.m │ ├── flagnear_rectangle_grid.m │ ├── makedatarows.m │ ├── max.m │ ├── min.m │ ├── move.m │ ├── mtimes.m │ ├── normals.m │ ├── normonesmat.m │ ├── onesmat.m │ ├── plot.m │ ├── plot_regions.m │ ├── plus.m │ ├── procverts.m │ ├── quiver.m │ ├── refine.m │ ├── reflect.m │ ├── rotate.m │ ├── scatter.m │ ├── signed_curvature.m │ ├── slicegraph.m │ ├── tangents.m │ ├── vertextract.m │ └── weights.m ├── @kernel │ ├── axissymhelm2d.m │ ├── axissymhelm2ddiff.m │ ├── elast2d.m │ ├── helm2d.m │ ├── helm2ddiff.m │ ├── helm2dquas.m │ ├── kernel.m │ ├── lap2d.m │ ├── minus.m │ ├── mrdivide.m │ ├── mtimes.m │ ├── nans.m │ ├── plus.m │ ├── rdivide.m │ ├── stok2d.m │ ├── times.m │ ├── uminus.m │ └── zeros.m ├── @trapper │ ├── arclength.m │ ├── area.m │ ├── max.m │ ├── min.m │ ├── normals.m │ ├── normonesmat.m │ ├── onesmat.m │ ├── plot.m │ ├── quiver.m │ ├── reverse.m │ ├── scatter.m │ ├── taus.m │ ├── trapper.m │ ├── weights.m │ └── whts.m ├── @trapperpref │ └── trapperpref.m ├── checkcurveparam.m ├── chunkerfit.m ├── chunkerflam.m ├── chunkerfunc.m ├── chunkerfuncuni.m ├── chunkerintegral.m ├── chunkerinterior.m ├── chunkerkerneval.m ├── chunkerkernevalmat.m ├── chunkermat.m ├── chunkermatapply.m ├── chunkerpoints.m ├── chunkerpoly.m ├── chunkgraphinit.m ├── chunkgraphinregion.m ├── demo │ ├── addpaths_loc.m │ ├── demo_KG.m │ ├── demo_Neumann_combined.m │ ├── demo_axissym_neumann.m │ ├── demo_barbell.m │ ├── demo_concentric_domain.png │ ├── demo_concentric_fields.png │ ├── demo_concentric_transmission.m │ ├── demo_data_field.m │ ├── demo_flam.m │ ├── demo_many_scatterers.m │ ├── demo_mixed_bc.m │ ├── demo_mult_connect.m │ ├── demo_neumann_combined_plot.png │ ├── demo_scatter.m │ ├── demo_scatter_slit.m │ ├── mixed_bc_plot.png │ └── planewave.m ├── ellipse.m ├── guide │ ├── addpaths_loc.m │ ├── expkernel.m │ ├── guide_chunkers.m │ ├── guide_chunkers_barbell.png │ ├── guide_chunkers_bymode.png │ ├── guide_chunkers_chunkerfit.png │ ├── guide_chunkers_circle.png │ ├── guide_chunkers_interior.png │ ├── guide_chunkers_shiftandreverse.png │ ├── guide_chunkers_starfish.png │ ├── guide_chunkgraphs.m │ ├── guide_chunkgraphs_curved_edges.png │ ├── guide_chunkgraphs_hawaiian.png │ ├── guide_chunkgraphs_polygon.png │ ├── guide_chunkgraphs_regions.png │ ├── guide_kernels.m │ ├── guide_simplebvps.m │ ├── guide_simplebvps_basicscattering.png │ ├── guide_simplebvps_laplaceneumann.png │ ├── guide_stokesvelocity.png │ └── planewave.m ├── hypoct_uni.m ├── mergeregions.m ├── nonflatinterface.m ├── pointinregion.m ├── redblue.m ├── regioninside.m ├── starfish.m ├── trapperfunc.m ├── trapperkerneval.m └── trappermat.m ├── devtools ├── docstyle │ ├── template_header.m │ └── template_header_license.txt └── test │ ├── absconvgaussTest.m │ ├── adapgausswtsTest.m │ ├── arclengthfunTest.m │ ├── axissymkernTest.m │ ├── axissymkernel_sphereTest.m │ ├── chunker_diffintmatTest.m │ ├── chunker_nearestTest.m │ ├── chunkerarcparamTest.m │ ├── chunkerclassunitTest.m │ ├── chunkerfitTest.m │ ├── chunkerfuncTest.m │ ├── chunkerfuncuniTest.m │ ├── chunkerintegralTest.m │ ├── chunkerinteriorTest.m │ ├── chunkerkerneval_correctionsTest.m │ ├── chunkerkerneval_gaussidTest.m │ ├── chunkerkerneval_greenhelmTest.m │ ├── chunkerkerneval_greenlapTest.m │ ├── chunkerkernevalmat_greenlapTest.m │ ├── chunkermatTest.m │ ├── chunkermat_axissymhelm2dTest.m │ ├── chunkermat_axissymhelm_neumannTest.m │ ├── chunkermat_axissymhelm_transmissionTest.m │ ├── chunkermat_axissymhelm_transmissionTest_re.m │ ├── chunkermat_helm2dTest.m │ ├── chunkermat_l2scaleTest.m │ ├── chunkermat_quadadapTest.m │ ├── chunkermat_quadadap_closetotouchingTest.m │ ├── chunkermat_stok2dTest.m │ ├── chunkermat_stok_tractiontest.m │ ├── chunkermat_truepolygonTest.m │ ├── chunkermatapplyTest.m │ ├── chunkerpolyTest.m │ ├── chunkgraph_basicTest.m │ ├── chunkgraph_lastlengthTest.m │ ├── chunkgrphconstructTest.m │ ├── chunkgrphrcipTest.m │ ├── chunkgrphrcipTransmissionTest.m │ ├── chunkgrphrcip_ignoreTest.m │ ├── chunkgrphregionTest.m │ ├── chunkrgrphOpdimTest.m │ ├── complexificationTest.m │ ├── datafieldTest.m │ ├── elastickernelsTest.m │ ├── flagnearTest.m │ ├── flagrectTest.m │ ├── flagselfTest.m │ ├── flamopdimsTest.m │ ├── flamproxybylevelTest.m │ ├── flamutilitiesTest.m │ ├── gradient_check.m │ ├── helm1d_greenTest.m │ ├── helm2d_greenTest.m │ ├── kernel_interleaveTest.m │ ├── kernelclassTest.m │ ├── kernelopTest.m │ ├── legeexpsunitTest.m │ ├── mixedbcTest.m │ ├── pquadTest.m │ ├── quasiperiodicTest.m │ ├── rcipTest.m │ ├── singularkernelTest.m │ ├── slicegraphTest.m │ ├── smootherTest.m │ ├── stokes_dtracTest.m │ └── trappermatTest.m ├── docs ├── Makefile ├── _static │ └── .keep ├── _templates │ └── .keep ├── assets │ └── images │ │ └── scatter_star_trim.png ├── conf.py ├── gallery.rst ├── getchunkie.rst ├── guide.rst ├── guide │ ├── chunkers.rst │ ├── chunkgraphbvps.rst │ ├── chunkgraphs.rst │ ├── kerns.rst │ ├── largerproblems.rst │ ├── simplebvps.rst │ └── transmission.rst ├── index.rst └── requirements.txt └── startup.m /.github/workflows/matlab.yml: -------------------------------------------------------------------------------- 1 | # based on Dan Fortunato's ultra SEM repo 2 | 3 | name: chunkie tests 4 | on: [push] 5 | jobs: 6 | ultraSEM-test: 7 | name: do chunkie tests 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Check out repository 11 | uses: actions/checkout@v2 12 | with: 13 | submodules: recursive 14 | - name: Install MATLAB 15 | uses: matlab-actions/setup-matlab@v0 16 | - name: Install FMMLIB 17 | run: cd chunkie/fmm2d; make matlab 18 | - name: Run commands 19 | uses: matlab-actions/run-command@v0 20 | with: 21 | command: cd('./devtools/test'); res = runtests; assert(all([res.Passed])) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *~ 3 | *# 4 | chunkie/demo-ignore/* 5 | *.save 6 | dev/* 7 | 8 | # Mac OS files 9 | *.DS_Store* 10 | 11 | # Matlab autosaves 12 | *.asv 13 | *.DS_STORE 14 | chunkie/FLAM 15 | chunkie/FLAM 16 | 17 | *~ 18 | *# 19 | chunkie/chunkergraph/test_chnkgraph_local.m 20 | chunkie/chunkergraph/local_tests/test_chnkgraph_local.m 21 | chunkie/chunkergraph/local_tests/test_chnkgraph_local2.m 22 | 23 | *k2test* 24 | *ktest* 25 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "FLAM"] 2 | path = chunkie/FLAM 3 | url = https://github.com/fastalgorithms/FLAM.git 4 | 5 | [submodule "chunkie/fmm2d"] 6 | path = chunkie/fmm2d 7 | url = https://github.com/flatironinstitute/fmm2d.git 8 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the OS, Python version and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.12" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the "docs/" directory with Sphinx 19 | sphinx: 20 | configuration: docs/conf.py 21 | 22 | # Optionally build your docs in additional formats such as PDF and ePub 23 | # formats: 24 | # - pdf 25 | # - epub 26 | 27 | # Optional but recommended, declare the Python requirements required 28 | # to build your documentation 29 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 30 | python: 31 | install: 32 | - requirements: docs/requirements.txt 33 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # This CITATION.cff file was generated with cffinit. 2 | # Visit https://bit.ly/cffinit to generate yours today! 3 | 4 | cff-version: 1.2.0 5 | title: 'chunkIE: a MATLAB integral equation toolbox' 6 | message: >- 7 | If you use this software, please cite it using the 8 | metadata from this file. 9 | type: software 10 | authors: 11 | - given-names: Travis 12 | family-names: Askham 13 | - given-names: Manas 14 | family-names: Rachh 15 | - given-names: Michael 16 | family-names: O'Neil 17 | - given-names: Jeremy 18 | family-names: Hoskins 19 | - given-names: Daniel 20 | family-names: Fortunato 21 | - given-names: Shidong 22 | family-names: Jiang 23 | - given-names: Fredrik 24 | family-names: Fryklund 25 | - given-names: Tristan 26 | family-names: Goodwill 27 | - given-names: Hai Yang 28 | family-names: Wang 29 | - given-names: Hai 30 | family-names: Zhu 31 | repository-code: 'https://github.com/fastalgorithms/chunkie' 32 | url: 'https://chunkie.readthedocs.io/' 33 | version: 1.0.0 34 | date-released: '2024-06-08' 35 | -------------------------------------------------------------------------------- /chunkie/+chnk/+arcparam/eval.m: -------------------------------------------------------------------------------- 1 | function [r,d,d2] = eval(s,param_data) 2 | % CHNK.ARCPARAM.EVAL evaluate arclength parameterization of a chunker 3 | % 4 | % get r, d, d2 at an arbitrary arclength point in a chunker 5 | % 6 | % s is the arclength and should lie in [0, sum(chnkr.wts)] 7 | % 8 | % param_data contains precomputed parameterization data (see 9 | % chunkerarcparam_init) 10 | % param_data.pstrt - arclength coordinate of left endpoints of all 11 | % panels 12 | % param_data.plen - arclength of all panels 13 | % param_data.cr - arclength legendre series of chhnkr.r 14 | % param_data.cd - arclength legendre series of chhnkr.d 15 | % param_data.cd2 - arclength legendre series of chhnkr.d2 16 | % param_data.k - chunker order 17 | % param_data.dim - chunker dimension 18 | % param_data.nch - number of chunks in chunkr 19 | % 20 | % see also CHNK.ARCPARAM.INIT 21 | 22 | % author: Tristan Goodwill 23 | 24 | % unpack data 25 | pstrt = param_data.pstrt; 26 | plen = param_data.plen; 27 | cr = param_data.cr; 28 | cd = param_data.cd; 29 | cd2 = param_data.cd2; 30 | k = param_data.k; 31 | dim = param_data.dim; 32 | nch = param_data.nch; 33 | 34 | % initialize variables 35 | ns = length(s); 36 | r = zeros(dim, ns); 37 | d = zeros(dim, ns); 38 | d2 = zeros(dim, ns); 39 | 40 | for i = 1:nch 41 | cri = cr(:,:,i); 42 | cdi = cd(:,:,i); 43 | cd2i = cd2(:,:,i); 44 | 45 | % determine points in this chunker 46 | iiin = (s >= pstrt(i)) & (s <= pstrt(i+1)); 47 | 48 | sloc = 2*(s(iiin)-pstrt(i))/plen(i) - 1; 49 | 50 | if ~isempty(sloc) 51 | % evaluate legendre series 52 | legs = lege.pols(sloc,k-1).'; 53 | r(:,iiin) = (legs*cri).'; 54 | d(:,iiin) = (legs*cdi).'; 55 | d2(:,iiin) = (legs*cd2i).'; 56 | end 57 | end 58 | 59 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+axissymhelm2d/asym_helm_data.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/+chnk/+axissymhelm2d/asym_helm_data.mat -------------------------------------------------------------------------------- /chunkie/+chnk/+axissymhelm2d/asym_helm_data2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/+chnk/+axissymhelm2d/asym_helm_data2.mat -------------------------------------------------------------------------------- /chunkie/+chnk/+axissymhelm2d/dalph.m: -------------------------------------------------------------------------------- 1 | function [dout] = dalph(r,dr,z) 2 | 3 | dout = {}; 4 | 5 | den = 2*r.^2+2*r.*dr+dr.^2+z.^2; 6 | num = 2*r.*dr+dr.^2+z.^2; 7 | val = num./den.^2; 8 | ar = -2*(r+dr).*val; 9 | num = -2*r.*dr-dr.^2+z.^2; 10 | val = num./den.^2; 11 | adr= -2*r.*val; 12 | az = 4*(r+dr).*r.*z./den.^2; 13 | 14 | dout.ar = ar; 15 | dout.adr= adr; 16 | dout.az = az; 17 | 18 | ardr = dr.^4+4*dr.^3.*r-8*dr.*r.^3-4*r.^4-z.^4; 19 | ardr = 2*ardr./den.^3; 20 | 21 | arz = 4*(r+dr).*z.*(dr.^2+2*dr.*r-2*r.^2+z.^2)./den.^3; 22 | adrz= -4*r.*z.*(3*dr.^2+6*dr.*r+2*r.^2-z.^2)./den.^3; 23 | azz = 4*r.*(r+dr).*(dr.^2+2*dr.*r+2*r.^2-3*z.^2)./den.^3; 24 | 25 | dout.ardr = ardr; 26 | dout.arz = arz; 27 | dout.adrz = adrz; 28 | dout.azz = azz; 29 | 30 | r0 = sqrt(r.^2+(r+dr).^2+z.^2); 31 | kr = r./r0; 32 | kdr = (r+dr)./r0; 33 | kz = z./r0; 34 | krdr = -r.*(r+dr)./r0.^3; 35 | krz = -r.*z./r0.^3; 36 | kdrz = -(r+dr).*z./r0.^3; 37 | kzz = (2*r.^2+2*r.*dr+dr.^2)./r0.^3; 38 | 39 | dout.kr = kr; 40 | dout.kdr = kdr; 41 | dout.kz = kz; 42 | dout.krdr= krdr; 43 | dout.krz = krz; 44 | dout.kdrz= kdrz; 45 | dout.kzz = kzz; 46 | 47 | end 48 | 49 | -------------------------------------------------------------------------------- /chunkie/+chnk/+axissymhelm2d/der_ak_to_grad.m: -------------------------------------------------------------------------------- 1 | function [dout] = der_ak_to_grad(r,q,z,i,ida,idk,... 2 | idaa,idak,idkk) 3 | 4 | dout = {}; 5 | dout.int = i; 6 | 7 | ds = chnk.axissymhelm2d.dalph(r,q,z); 8 | 9 | intdr = ds.ar.*ida +ds.kr.*idk; 10 | intdq = ds.adr.*ida+ds.kdr.*idk; 11 | intdz = ds.az.*ida +ds.kz.*idk; 12 | 13 | intdrq= ds.ardr.*ida + ds.krdr.*idk + ... 14 | ds.ar.*ds.adr.*idaa + ds.kr.*ds.kdr.*idkk + ... 15 | ds.ar.*ds.kdr.*idak+ds.kr.*ds.adr.*idak; 16 | 17 | intdrz= ds.arz.*ida + ds.krz.*idk + ... 18 | ds.ar.*ds.az.*idaa + ds.kr.*ds.kz.*idkk + ... 19 | ds.ar.*ds.kz.*idak+ds.kr.*ds.az.*idak; 20 | 21 | intdqz= ds.adrz.*ida + ds.kdrz.*idk + ... 22 | ds.adr.*ds.az.*idaa + ds.kdr.*ds.kz.*idkk + ... 23 | ds.adr.*ds.kz.*idak+ds.kdr.*ds.az.*idak; 24 | 25 | intdzz= ds.azz.*ida + ds.kzz.*idk + ... 26 | ds.az.*ds.az.*idaa + ds.kz.*ds.kz.*idkk + ... 27 | ds.az.*ds.kz.*idak+ds.kz.*ds.az.*idak; 28 | 29 | dout.intdr = intdr; 30 | dout.intdq = intdq; 31 | dout.intdz = intdz; 32 | 33 | dout.intdrq = intdrq; 34 | dout.intdrz = intdrz; 35 | dout.intdqz = intdqz; 36 | dout.intdzz = intdzz; 37 | 38 | end 39 | 40 | -------------------------------------------------------------------------------- /chunkie/+chnk/+axissymhelm2d/div_by_kap.m: -------------------------------------------------------------------------------- 1 | function [dout] = div_by_kap(r,q,z,dfunc) 2 | 3 | r0 = sqrt(r.^2+(r+q).^2+z.^2); 4 | i0 = 1./r0; 5 | i0da = 0; 6 | i0dk = -1./r0.^2; 7 | i0daa= 0; 8 | i0dak= 0; 9 | i0dkk= 2./r0.^3; 10 | [dout] = chnk.axissymhelm2d.der_ak_to_grad(r,q,z,i0,i0da,i0dk,... 11 | i0daa,i0dak,i0dkk); 12 | 13 | i = dfunc.int.*i0; 14 | idr = dfunc.int.*dout.intdr + dfunc.intdr.*dout.int; 15 | idq = dfunc.int.*dout.intdq + dfunc.intdq.*dout.int; 16 | idz = dfunc.int.*dout.intdz + dfunc.intdz.*dout.int; 17 | idqr = dfunc.intdrq.*dout.int + dfunc.int.*dout.intdrq + ... 18 | dfunc.intdr.*dout.intdq + dfunc.intdq.*dout.intdr; 19 | idrz = dfunc.intdrz.*dout.int + dfunc.int.*dout.intdrz + ... 20 | dfunc.intdr.*dout.intdz + dfunc.intdz.*dout.intdr; 21 | idqz = dfunc.intdqz.*dout.int + dfunc.int.*dout.intdqz + ... 22 | dfunc.intdq.*dout.intdz + dfunc.intdz.*dout.intdq; 23 | idzz = dfunc.intdzz.*dout.int + dfunc.int.*dout.intdzz + ... 24 | 2*dfunc.intdz.*dout.intdz; 25 | 26 | dout.int = i; 27 | dout.intdr = idr; 28 | dout.intdq = idq; 29 | dout.intdz = idz; 30 | dout.intdrq = idqr; 31 | dout.intdrz = idrz; 32 | dout.intdqz = idqz; 33 | dout.intdzz = idzz; 34 | 35 | end 36 | 37 | -------------------------------------------------------------------------------- /chunkie/+chnk/+curves/bymode.m: -------------------------------------------------------------------------------- 1 | 2 | function [r,d,d2] = bymode(t,modes,ctr,sc) 3 | %CHNK.CURVES.BYMODE evaluate the position, and first and second derivatives 4 | % of the position described by r(t) = ctr + (modes(1) + modes(2)*cos(t) + 5 | % modes(3)*sin(t) + modes(4)*cos(2t) + modes(5)*sin(2t) ...)[cos(t),sin(t)] 6 | 7 | if nargin < 3 8 | ctr = zeros(2,1); 9 | sc = [1;1]; 10 | end 11 | if(nargin < 4) 12 | sc = [1,1]; 13 | end 14 | 15 | 16 | 17 | x0 = ctr(1); y0 = ctr(2); 18 | 19 | eitfac = ones(size(t)); 20 | r = modes(1)*ones(size(t)); 21 | rp = 0.0; rpp = 0.0; 22 | eit = exp(1i*t); 23 | for i = 2:2:length(modes) 24 | eitfac = eitfac.*eit; 25 | ih = i/2; 26 | r = r + real(eitfac)*modes(i); 27 | rp = rp - ih*imag(eitfac)*modes(i); 28 | rpp = rpp - ih^2*real(eitfac)*modes(i); 29 | if i < length(modes) 30 | r = r + imag(eitfac)*modes(i+1); 31 | rp = rp + ih*real(eitfac)*modes(i+1); 32 | rpp = rpp - ih^2*imag(eitfac)*modes(i+1); 33 | end 34 | end 35 | 36 | xs = x0+r.*real(eit)*sc(1); 37 | ys = y0+r.*imag(eit)*sc(2); 38 | dxdr = real(eit); 39 | dydr = imag(eit); 40 | 41 | dxdth = -r.*imag(eit); 42 | dxdth2 = -r.*real(eit); 43 | dydth = r.*real(eit); 44 | dydth2 = -r.*imag(eit); 45 | 46 | dxdrdth = -imag(eit); 47 | dydrdth = real(eit); 48 | 49 | dxs = dxdr.*rp+dxdth; 50 | dys = dydr.*rp+dydth; 51 | 52 | d2xs = dxdr.*rpp+(dxdrdth*2.0d0).*rp+dxdth2; 53 | d2ys = dydr.*rpp+(dydrdth*2.0d0).*rp+dydth2; 54 | 55 | r = [(xs(:)).'; (ys(:)).']; 56 | d = [(sc(1)*dxs(:)).'; (sc(2)*dys(:)).']; 57 | d2 = [(sc(1)*d2xs(:)).'; (sc(2)*d2ys(:)).']; 58 | 59 | end 60 | 61 | -------------------------------------------------------------------------------- /chunkie/+chnk/+curves/fpara.m: -------------------------------------------------------------------------------- 1 | function [r,d,d2] = fpara(t,a,b) 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % 4 | % a*(t-b)^2 5 | % 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | 8 | ts = size(t); 9 | tt = t(:); 10 | 11 | rx = tt; 12 | ry = a*(tt-b).^2; 13 | 14 | dx = 1*ones(size(rx)); 15 | dy = 2*a*(tt-b); 16 | 17 | d2x= zeros(size(rx)); 18 | d2y= 2*a(ones(size(d2x))); 19 | 20 | r = [rx.';ry.']; 21 | d = [dx.';dy.']; 22 | d2= [d2x.';d2y.']; 23 | 24 | r = reshape(r,[2,ts]); 25 | d = reshape(d,[2,ts]); 26 | d2= reshape(d2,[2,ts]); 27 | 28 | end 29 | 30 | -------------------------------------------------------------------------------- /chunkie/+chnk/+curves/fsine.m: -------------------------------------------------------------------------------- 1 | function [r,d,d2] = fsine(t,a,b,c) 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % 4 | % a*sin(b*t+c) 5 | % 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | ts = size(t); 8 | tt = t(:); 9 | 10 | rx = tt; 11 | ry = a*sin(b*tt+c); 12 | 13 | dx = 1*ones(size(rx)); 14 | dy = a*b*cos(b*tt+c); 15 | 16 | d2x= zeros(size(rx)); 17 | d2y=-a*b*b*sin(b*tt+c); 18 | 19 | r = [rx.';ry.']; 20 | d = [dx.';dy.']; 21 | d2= [d2x.';d2y.']; 22 | 23 | r = reshape(r,[2,ts]); 24 | d = reshape(d,[2,ts]); 25 | d2= reshape(d2,[2,ts]); 26 | 27 | end 28 | 29 | -------------------------------------------------------------------------------- /chunkie/+chnk/+curves/linefunc.m: -------------------------------------------------------------------------------- 1 | function [r,d,d2] = linefunc(t,v1,v2) 2 | sizet = size(t); 3 | ts = t(:).'; 4 | r = v1 + (v2-v1)*ts; 5 | d = (v2-v1)*ones(size(ts)); 6 | d2 = zeros(size(d)); 7 | r = reshape(r,[2,sizet]); 8 | d = reshape(d,[2,sizet]); 9 | d2= reshape(d2,[2,sizet]); 10 | end 11 | -------------------------------------------------------------------------------- /chunkie/+chnk/+demo/barbell.m: -------------------------------------------------------------------------------- 1 | function verts = barbell(s1,s2,hb,lb) 2 | %BARBELL 3 | % 4 | % Input (all optional) 5 | % s1 - side length of left square (4.0) 6 | % s2 - side length of right square (3.0) 7 | % hb - height of bridge between squares (1.0) 8 | % lb - length of bridge (2.5) 9 | % 10 | 11 | if nargin < 1; s1 = 2.0; end 12 | if nargin < 2; s2 = 2.0; end 13 | if nargin < 3; hb = 0.5; end 14 | if nargin < 4; lb = 1.0; end 15 | 16 | verts_sqr1 = s1/2.0*[1, -1, -1, 1; 1, 1, -1, -1]; 17 | verts_sqr2 = s2/2.0*[-1, 1, 1, -1; -1, -1, 1, 1]; 18 | 19 | wbrdg = hb/2.0; 20 | 21 | ctr_sqr1 = [-(s1/2.0+lb/2.0); 0.0]; 22 | ctr_sqr2 = [(s2/2.0+lb/2.0); 0.0]; 23 | 24 | verts_sqr1 = verts_sqr1 + repmat(ctr_sqr1,1,size(verts_sqr1,2)); 25 | verts_sqr2 = verts_sqr2 + repmat(ctr_sqr2,1,size(verts_sqr2,2)); 26 | 27 | verts1 = [verts_sqr1(1,end), verts_sqr2(1,1); -wbrdg, -wbrdg]; 28 | verts2 = [verts_sqr2(1,end), verts_sqr1(1,1); wbrdg, wbrdg]; 29 | 30 | verts = [verts_sqr1, verts1, verts_sqr2, verts2]; -------------------------------------------------------------------------------- /chunkie/+chnk/+flam/proxy_circ_pts.m: -------------------------------------------------------------------------------- 1 | 2 | function [proxy,pnorm,pw] = proxy_circ_pts(p) 3 | 4 | if nargin < 1 5 | p = 64; 6 | end 7 | 8 | theta = (0:(p-1))*2*pi/p; 9 | 10 | proxy = [1.5*cos(theta); 1.5*sin(theta)]; 11 | 12 | pnorm = [cos(theta); sin(theta)]; 13 | 14 | pw = ones(p,1)*(2.0*pi*1.5)/p; 15 | 16 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+flam/proxy_rect_pts.m: -------------------------------------------------------------------------------- 1 | function [pr,ptau,pw,pin] = proxy_rect_pts(lxy, npxy, opts) 2 | %PROXY_SQUARE_PTS return the proxy points, unit tangents, weights, and 3 | % function handle for determining if points are within proxy surface. 4 | % This function is for the proxy surface around a unit box centered at 5 | % the origin. The proxy points lie on the 6 | % [-lxy(1),lxy(1)]*[-lxy(2), lxy(2)] rectangle 7 | % 8 | % Input: 9 | % lxy(2) - half edge lengths in x and y direction 10 | % npxy(2) - number of proxy points in x and y direction 11 | % opts - optional input 12 | % opts.iflege (false) whether to use legendre or equispaced nodes 13 | % 14 | % Output: 15 | % pr - (2,2*(npxy(1) + npxy(2))) array of proxy point locations 16 | % 17 | 18 | 19 | if nargin < 1 20 | lxy = [1,1]; 21 | end 22 | 23 | if nargin < 2 24 | npxy = [10, 10]; 25 | end 26 | 27 | if nargin < 3 28 | opts = []; 29 | end 30 | 31 | iflege = 0; 32 | if isfield(opts, 'iflege') 33 | iflege = opts.iflege; 34 | end 35 | 36 | nx = npxy(1); 37 | ny = npxy(2); 38 | 39 | lx = lxy(1); 40 | ly = lxy(2); 41 | 42 | 43 | if ~iflege 44 | pts_x = -lx +2*lx*(0:(nx-1))*1.0/nx; 45 | pw_x = ones(nx,1)*(2*lx/nx); 46 | 47 | pts_y = -ly +2*ly*(0:(ny-1))*1.0/ny; 48 | pw_y = ones(ny,1)*(2*ly/ny); 49 | else 50 | [pts_x, pw_x] = lege.exps(nx); 51 | [pts_y, pw_y] = lege.exps(ny); 52 | pts_x = pts_x.'*lx; 53 | pw_x = pw_x*lx; 54 | 55 | pts_y = pts_y.'*ly; 56 | pw_y = pw_y*ly; 57 | 58 | end 59 | 60 | 61 | one_x = ones(size(pts_x)); 62 | one_y = ones(size(pts_y)); 63 | 64 | pr = [pts_x, one_y*lx, -pts_x, -lx*one_y; 65 | -ly*one_x, pts_y, ly*one_x, -pts_y]; 66 | 67 | pw = [pw_x; pw_y; pw_x; pw_y]; 68 | 69 | ptau = [one_x, one_y*0, -one_x, one_y*0; 70 | one_x*0, one_y, one_x*0, -one_y]; 71 | 72 | pin = @(x) max(abs(x./lpxy),[],1) < 1; 73 | 74 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+flam/proxy_square_pts.m: -------------------------------------------------------------------------------- 1 | function [pr,ptau,pw,pin] = proxy_square_pts(porder, opts) 2 | %PROXY_SQUARE_PTS return the proxy points, unit tangents, weights, and 3 | % function handle for determining if points are within proxy surface. 4 | % This function is for the proxy surface around a unit box centered at 5 | % the origin. The proxy points lie on the [-1.5,1.5]^2 square 6 | % 7 | % Input: 8 | % porder - number of points on proxy surface 9 | % 10 | % Output: 11 | % pr - (2,porder) array of proxy point locations (centered at 0 for a 12 | % box of side length 1) 13 | 14 | if nargin < 1 15 | porder = 64; 16 | end 17 | 18 | if nargin < 2 19 | opts = []; 20 | end 21 | 22 | iflege = 1; 23 | if isfield(opts, 'iflege') 24 | iflege = opts.iflege; 25 | end 26 | 27 | assert(mod(porder,4) == 0, ... 28 | 'number of proxy points on square should be multiple of 4') 29 | 30 | po4 = porder/4; 31 | 32 | if ~iflege 33 | pts = -1.5+3*(0:(po4-1))*1.0/po4; 34 | one = ones(size(pts)); 35 | pw = ones(porder,1)*(4.0*3.0/porder); 36 | else 37 | % generate panel Gauss-Legendre rule on [-1.5, 1.5] 38 | % because large single-panel rules lose digits 39 | k = min(16, po4); 40 | npanel = po4/k; 41 | [pts, wts] = lege.exps(k); 42 | panels = linspace(-1.5, 1.5, npanel + 1); 43 | pts = reshape(panels(1:end-1) + 3/(2*npanel) * (pts + 1), 1, []); 44 | wts = 3/(2*npanel) * repmat(wts, npanel, 1)'; 45 | one = ones(1,porder/4); 46 | pw = repmat(wts', 4, 1); 47 | end 48 | 49 | pr = [pts, one*1.5, -pts, -1.5*one; 50 | -1.5*one, pts, 1.5*one, -pts]; 51 | 52 | ptau = [one, one*0, -one, one*0; 53 | one*0, one, one*0, -one]; 54 | 55 | pin = @(x) max(abs(x),[],1) < 1.5; 56 | 57 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+helm1d/green.m: -------------------------------------------------------------------------------- 1 | function [val,grad,hess] = green(zkE,src,targ) 2 | %CHNK.HELM1D.GREEN evaluate the 1D helmholtz green's function 3 | % for the given sources and targets 4 | 5 | [~,ns] = size(src); 6 | [~,nt] = size(targ); 7 | 8 | xs = repmat(src(1,:),nt,1); 9 | ys = repmat(src(2,:),nt,1); 10 | 11 | xt = repmat(targ(1,:).',1,ns); 12 | yt = repmat(targ(2,:).',1,ns); 13 | 14 | rx = xt-xs; 15 | ry = yt-ys; 16 | 17 | rx2 = rx.*rx; 18 | ry2 = ry.*ry; 19 | 20 | r2 = rx2+ry2; 21 | 22 | r = sqrt(r2); 23 | 24 | 25 | if nargout > 0 26 | val = exp(1j*zkE*r); 27 | end 28 | 29 | [m,n] = size(xs); 30 | 31 | if nargout > 1 32 | grad = zeros(m,n,2); 33 | 34 | grad(:,:,1) = (1/2).*(rx./r).*exp(1j*zkE*r); 35 | grad(:,:,2) = (1/2).*(ry./r).*exp(1j*zkE*r); 36 | grad = 2*1j*zkE*grad; 37 | end 38 | 39 | if nargout > 2 40 | 41 | hess = zeros(m,n,3); 42 | 43 | r3 = r.^3; 44 | 45 | hess(:,:,1) = (1./(2*r3)).*(1j*zkE*r.*rx2 - rx2 + r2).*exp(1j*zkE*r); 46 | hess(:,:,2) = (1./(2*r3)).*(1j*zkE*r.*rx.*ry - rx.*ry).*exp(1j*zkE*r); 47 | hess(:,:,3) = (1./(2*r3)).*(1j*zkE*r.*ry2 - ry2 + r2).*exp(1j*zkE*r); 48 | hess = 2*1j*zkE*hess; 49 | end 50 | -------------------------------------------------------------------------------- /chunkie/+chnk/+helm1d/sweep.m: -------------------------------------------------------------------------------- 1 | function pot = sweep(uin,inds,ts,wts,zkE) 2 | %sweeping algorithm for preconditioner 3 | 4 | vexpsp = exp(1i*diff(ts)*zkE); 5 | 6 | u = zeros([numel(wts),1]); 7 | u(inds) = uin; 8 | 9 | nt = numel(u); 10 | chrg = u.*(wts); 11 | 12 | voutp = zeros([nt,1]); 13 | voutp(1) = chrg(1); 14 | 15 | for i=2:nt 16 | voutp(i) = vexpsp(i-1)*voutp(i-1)+chrg(i); 17 | end 18 | 19 | voutm = zeros([nt,1]); 20 | chrg = flipud(chrg); 21 | vexpsp= flipud(vexpsp); 22 | 23 | for i=2:nt 24 | voutm(i) = vexpsp(i-1)*(voutm(i-1)+chrg(i-1)); 25 | end 26 | 27 | pot = voutp + flipud(voutm); 28 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+helm2d/besseldiff_etc_pscoefs.m: -------------------------------------------------------------------------------- 1 | function [cf1,cf2] = besseldiff_etc_pscoefs(nterms) 2 | % powerseries coefficients for J_0 - 1 and the other series in 3 | % definition of Y_0 4 | % 5 | % these are both series with the terms z^2,z^4,z^6,..z^(2*nterms) 6 | % 7 | % cf1 are power series coeffs of even terms (excluding constant) 8 | % for J_0(z) - 1 9 | % 10 | % cf2 are power series coeffs for the similar series 11 | % z^2/4 - (1+1/2)*(z^2/4)^2/(2!)^2 + (1+1/2+1/3)*(z^2/4)^3/(3!)^2 - ... 12 | % 13 | % which appears in the power series for H_0(z) 14 | 15 | sum1 = 0; 16 | fac1 = 1; 17 | pow1 = 1; 18 | 19 | cf1 = zeros(nterms,1); 20 | cf2 = zeros(nterms,1); 21 | sgn = 1; 22 | 23 | for j = 1:nterms 24 | fac1 = fac1/(j*j); 25 | sum1 = sum1 + 1.0/j; 26 | pow1 = pow1*0.25; 27 | cf1(j) = -sgn*pow1*fac1; 28 | cf2(j) = sgn*sum1*pow1*fac1; 29 | sgn = -sgn; 30 | end 31 | 32 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+helm2d/even_pseval.m: -------------------------------------------------------------------------------- 1 | function [v] = even_pseval(cf,x) 2 | % evaluates an even power series with no constant term 3 | % with coefficients given in cf. 4 | % 5 | % x can be an array 6 | 7 | x2 = x.*x; 8 | 9 | xp = x2; 10 | 11 | v = zeros(size(x)); 12 | 13 | nterms = length(cf); 14 | for j = 1:nterms 15 | v = v + cf(j)*xp; 16 | xp = xp.*x2; 17 | end 18 | -------------------------------------------------------------------------------- /chunkie/+chnk/+helm2d/green.m: -------------------------------------------------------------------------------- 1 | function [val,grad,hess] = green(k,src,targ) 2 | %CHNK.HELM2D.GREEN evaluate the helmholtz green's function 3 | % for the given sources and targets 4 | 5 | [~,ns] = size(src); 6 | [~,nt] = size(targ); 7 | 8 | xs = repmat(src(1,:),nt,1); 9 | ys = repmat(src(2,:),nt,1); 10 | 11 | xt = repmat(targ(1,:).',1,ns); 12 | yt = repmat(targ(2,:).',1,ns); 13 | 14 | rx = xt-xs; 15 | ry = yt-ys; 16 | 17 | rx2 = rx.*rx; 18 | ry2 = ry.*ry; 19 | 20 | r2 = rx2+ry2; 21 | 22 | r = sqrt(r2); 23 | 24 | 25 | if nargout > 0 26 | h0 = besselh(0,1,k*r); 27 | val = 0.25*1i*h0; 28 | end 29 | 30 | [m,n] = size(xs); 31 | 32 | if nargout > 1 33 | h1 = besselh(1,1,k*r); 34 | grad = zeros(m,n,2); 35 | 36 | grad(:,:,1) = -1i*k*0.25*h1.*rx./r; 37 | grad(:,:,2) = -1i*k*0.25*h1.*ry./r; 38 | 39 | end 40 | 41 | if nargout > 2 42 | 43 | hess = zeros(m,n,3); 44 | 45 | r3 = r.^3; 46 | 47 | h2 = 2*h1./(k*r)-h0; 48 | 49 | hess(:,:,1) = 0.25*1i*k*((rx-ry).*(rx+ry).*h1./r3 - k*rx2.*h0./r2); 50 | hess(:,:,2) = 0.25*1i*k*k*rx.*ry.*h2./r2; 51 | hess(:,:,3) = 0.25*1i*k*((ry-rx).*(rx+ry).*h1./r3 - k*ry2.*h0./r2); 52 | end 53 | -------------------------------------------------------------------------------- /chunkie/+chnk/+helm2dquas/latticecoefs.m: -------------------------------------------------------------------------------- 1 | function S = latticecoefs(n,zk,d,kappa,alpha,a,M,l) 2 | %CHNK.HELMQUAS.LATTICECOEFS precompute lattice sum integrals 3 | % i.e. local coefficients for the representation 4 | % G_far(x,y) := sum_|n|>l i/4 H_0^{(1)}(zk |x- n d e_1-y|) 5 | % exp(i kapppa d n) 6 | % = sum_n=0^inf Sn J_n(zk |x-y|) cos(n arg(x-y)) 7 | % 8 | % (see Yasumoto and K. Yoshitomi (1999)) 9 | % 10 | % computes the nth order lattice sum using trapezoid rule on the interval 11 | % [0,a] with M points 12 | % 13 | % quasi periodic parameters: 14 | % d - period 15 | % kappa - quasiperiodic parameters 16 | % alpha - exp(1i*d*kappa), chosen so that u(x+d) = alpha * u(x) 17 | 18 | if nargin < 8, l = 2; end 19 | taus = linspace(0,a,M)*(1-1i); 20 | 21 | nkappa = length(kappa); 22 | S = zeros(nkappa,length(n)); 23 | 24 | sq_taus = sqrt(1-taus.^2); 25 | 26 | Gp = exp(n*log(taus - 1i*sq_taus) +l*1i*zk*d*sq_taus); 27 | Gm = exp(n*log(-taus - 1i*sq_taus) +l*1i*zk*d*sq_taus); 28 | 29 | 30 | for i = 1:nkappa 31 | 32 | Fp = 1./(sq_taus.*(1-exp(1i*zk*d.*(sq_taus-kappa(i)*d./zk/d)))); 33 | Fm = 1./(sq_taus.*(1-exp(1i*zk*d.*(sq_taus+kappa(i)*d./zk/d)))); 34 | 35 | S_p = sum((Gp+Gm).*Fp,2)-(Gp(:,1)+Gm(:,1)).*Fp(:,1)/2; 36 | S_m = sum((Gp+Gm).*Fm,2)-(Gp(:,1)+Gm(:,1)).*Fm(:,1)/2; 37 | 38 | S(i,:) = -1i*exp(1i*pi/4)*sqrt(2)/pi*((-1).^n.*alpha(i)^(-l).*S_p+alpha(i)^(l)*S_m)*a/(M-1); 39 | end 40 | 41 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+intchunk/fcoefs.m: -------------------------------------------------------------------------------- 1 | function fint = chunkerintchunk_fcoefs(fc,dc) 2 | 3 | 4 | dsdtfun = @(t) sqrt(sum((lege.exev(t,dc.').^2).',1)); 5 | fintfun = @(t) lege.exev(t,fc).*dsdtfun(t); 6 | 7 | fint = quadgk(fintfun,-1,1); -------------------------------------------------------------------------------- /chunkie/+chnk/+intchunk/fhandle.m: -------------------------------------------------------------------------------- 1 | function fint = chunkerintchunk_fhandle(f,rc,dc) 2 | 3 | dsdtfun = @(t) sqrt(sum((lege.exev(t,dc.').^2).',1)); 4 | fintfun = @(t) f(lege.exev(t,rc.').').*dsdtfun(t); 5 | 6 | fint = quadgk(fintfun,-1,1); 7 | 8 | end 9 | -------------------------------------------------------------------------------- /chunkie/+chnk/+intchunk/kerncoefs.m: -------------------------------------------------------------------------------- 1 | function fint = kerncoefs(kern,opdims,rdim,fc, ... 2 | rci,dci,d2ci,targ,quadgkparams) 3 | 4 | fintfun = @(t) fkerneval(t,kern,fc,rci,dci,d2ci,targ,opdims,rdim); 5 | 6 | fint = quadgk(fintfun,-1,1,quadgkparams{:}); 7 | 8 | end 9 | 10 | function fvals = fkerneval(t,kern,fc,rci,dci,d2ci,targ,opdims,... 11 | rdim) 12 | 13 | densvals = zeros(opdims(2),length(t)); 14 | for i = 1:opdims(2) 15 | densvals(i,:) = lege.exev(t,fc(:,i)); 16 | end 17 | 18 | [dim,k] = size(rci); 19 | 20 | ri = lege.exev(t,rci.').'; 21 | di = lege.exev(t,dci.').'; 22 | d2i = lege.exev(t,d2ci.').'; 23 | 24 | targinfo = []; targinfo.r = targ; 25 | srcinfo = []; srcinfo.r = ri; srcinfo.d = di; srcinfo.d2 = d2i; 26 | dsdt = sqrt(sum(di.^2,1)); 27 | kernmat = kern(srcinfo,targinfo); 28 | kernmat = kernmat(rdim:opdims(1):end,:); 29 | 30 | kernmat = reshape(kernmat,opdims(2),length(t)); 31 | fvals = kernmat.*densvals; 32 | fvals = sum(fvals,1); 33 | fvals = reshape(fvals,size(t)).*dsdt; 34 | 35 | end 36 | 37 | -------------------------------------------------------------------------------- /chunkie/+chnk/+lap2d/green.m: -------------------------------------------------------------------------------- 1 | 2 | function [val,grad,hess] = green(src,targ,nolog) 3 | 4 | if (nargin < 3) 5 | nolog = false; 6 | end 7 | 8 | [~,ns] = size(src); 9 | [~,nt] = size(targ); 10 | 11 | rx = bsxfun(@minus,targ(1,:).',src(1,:)); 12 | ry = bsxfun(@minus,targ(2,:).',src(2,:)); 13 | r2 = rx.^2+ry.^2; 14 | 15 | 16 | if (nargout > 0) 17 | 18 | if nolog 19 | val = []; 20 | else 21 | val = -log(r2)/(4.0*pi); 22 | end 23 | 24 | end 25 | 26 | if nargout > 1 27 | 28 | grad = zeros(nt,ns,2); 29 | 30 | grad(:,:,1) = -rx./(2.0*pi*r2); 31 | grad(:,:,2) = -ry./(2.0*pi*r2); 32 | 33 | end 34 | 35 | if nargout > 2 36 | rx2 = rx.*rx; 37 | ry2 = ry.*ry; 38 | 39 | 40 | r4 = r2.*r2; 41 | 42 | hess = zeros(nt,ns,3); 43 | 44 | hess(:,:,1) = rx2./(pi*r4)-1.0./(2.0*pi*r2); 45 | hess(:,:,2) = rx.*ry./(pi*r4); 46 | hess(:,:,3) = ry2./(pi*r4)-1.0./(2.0*pi*r2); 47 | end 48 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadba/getlogquad.m: -------------------------------------------------------------------------------- 1 | function [xs,ws,nskip] = getlogquad(norder) 2 | 3 | filename= '+chnk/+quadba/logwhts.mat'; 4 | 5 | persistent whts_dict 6 | if isempty(whts_dict) 7 | load(filename,'whts_dict'); 8 | assert(~isempty(whts_dict),'failed to load!') 9 | end 10 | 11 | assert(isKey(whts_dict,norder),'not an available integration order'); 12 | 13 | whts = whts_dict(norder); 14 | 15 | xs = whts.xs; ws = whts.ws; nskip = whts.nskip; 16 | 17 | end 18 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadba/logavail.m: -------------------------------------------------------------------------------- 1 | function iords = logavail() 2 | 3 | filename= '+chnk/+quadba/logwhts.mat'; 4 | 5 | persistent whts_dict 6 | if isempty(whts_dict) 7 | load(filename,'whts_dict'); 8 | assert(~isempty(whts_dict),'failed to load!') 9 | end 10 | 11 | iords = cell2mat(keys(whts_dict)); 12 | 13 | end 14 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadba/logwhts.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/+chnk/+quadba/logwhts.mat -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/ggqnear.m: -------------------------------------------------------------------------------- 1 | function [xs1,ws1] = ggqnear(kmax) 2 | 3 | switch kmax 4 | case 16 5 | [xs1,ws1] = chnk.quadggq.ggqnear16(); 6 | case 20 7 | [xs1,ws1] = chnk.quadggq.ggqnear20(); 8 | case 24 9 | [xs1,ws1] = chnk.quadggq.ggqnear24(); 10 | case 30 11 | [xs1,ws1] = chnk.quadggq.ggqnear30(); 12 | case 40 13 | [xs1,ws1] = chnk.quadggq.ggqnear40(); 14 | case 60 15 | [xs1,ws1] = chnk.quadggq.ggqnear60(); 16 | otherwise 17 | error('near kmax selection not available') 18 | end 19 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/ggqself_nnode001_npoly002.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = ggqself_nnode001_npoly002() 2 | xs0 = cell( 1,1); 3 | ws0 = cell( 1,1); 4 | xs0{ 1} = [ 5 | -.36787944117144232159552376996562168E+00 6 | 0.36787944117144232159552376996562168E+00 7 | ]; 8 | ws0{ 1} = [ 9 | 0.10000000000000000000000000000000040E+01 10 | 0.10000000000000000000000000000000039E+01 11 | ]; 12 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/ggqself_nnode001_npoly003.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = ggqself_nnode001_npoly003() 2 | xs0 = cell( 1,1); 3 | ws0 = cell( 1,1); 4 | xs0{ 1} = [ 5 | -.86163790754222582939713388595239318E+00 6 | -.11777019747430538684569124453375993E+00 7 | 0.61328873086007008726700163630436939E+00 8 | ]; 9 | ws0{ 1} = [ 10 | 0.47597161144992864209060728625792419E+00 11 | 0.71752663504774251604307023871322486E+00 12 | 0.80650175350232884186632247502885293E+00 13 | ]; 14 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/ggqself_nnode002_npoly004.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = ggqself_nnode002_npoly004() 2 | xs0 = cell( 2,1); 3 | ws0 = cell( 2,1); 4 | xs0{ 2} = [ 5 | -.71628866320479239618537346209102707E+00 6 | 0.11418523491133174545762725656738753E+00 7 | 0.61147624389712400654434872283186184E+00 8 | 0.90223606625179221895791121195536941E+00 9 | ]; 10 | ws0{ 2} = [ 11 | 0.67868688971312281958678978763537695E+00 12 | 0.79498356304164494862053187566414017E+00 13 | 0.27346680687870896083557985247561209E+00 14 | 0.25286274036652327095709848422487224E+00 15 | ]; 16 | xs0{ 1} = [ 17 | 0.71628866320479239618537346209102707E+00 18 | -.11418523491133174545762725656738753E+00 19 | -.61147624389712400654434872283186184E+00 20 | -.90223606625179221895791121195536941E+00 21 | ]; 22 | ws0{ 1} = [ 23 | 0.67868688971312281958678978763537695E+00 24 | 0.79498356304164494862053187566414017E+00 25 | 0.27346680687870896083557985247561209E+00 26 | 0.25286274036652327095709848422487224E+00 27 | ]; 28 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/ggqself_nnode002_npoly006.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = ggqself_nnode002_npoly006() 2 | xs0 = cell( 2,1); 3 | ws0 = cell( 2,1); 4 | xs0{ 2} = [ 5 | -.89953996972438780747077754816803212E+00 6 | -.48215995386084649613577883624705580E+00 7 | 0.10519469833060595806768193327804493E+00 8 | 0.53034203202873531259193565898511033E+00 9 | 0.70611436808930569797174132770120591E+00 10 | 0.92353365601546958135573575010893067E+00 11 | ]; 12 | ws0{ 2} = [ 13 | 0.25897667224439155530594347204096681E+00 14 | 0.54972171690193292464613240919851853E+00 15 | 0.56445702843298770830143059691795498E+00 16 | 0.24628915723673340875414944682405044E+00 17 | 0.19978658253079509403335534318607661E+00 18 | 0.18076884265315930895898873183243766E+00 19 | ]; 20 | xs0{ 1} = [ 21 | 0.89953996972438780747077754816803212E+00 22 | 0.48215995386084649613577883624705580E+00 23 | -.10519469833060595806768193327804493E+00 24 | -.53034203202873531259193565898511033E+00 25 | -.70611436808930569797174132770120591E+00 26 | -.92353365601546958135573575010893067E+00 27 | ]; 28 | ws0{ 1} = [ 29 | 0.25897667224439155530594347204096681E+00 30 | 0.54972171690193292464613240919851853E+00 31 | 0.56445702843298770830143059691795498E+00 32 | 0.24628915723673340875414944682405044E+00 33 | 0.19978658253079509403335534318607661E+00 34 | 0.18076884265315930895898873183243766E+00 35 | ]; 36 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/ggqself_nnode003_npoly006.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = ggqself_nnode003_npoly006() 2 | xs0 = cell( 3,1); 3 | ws0 = cell( 3,1); 4 | xs0{ 2} = [ 5 | -.87009876131956772613858095886641301E+00 6 | -.44185506329862696502069589276343663E+00 7 | -.67223041203149404461512935128828627E-01 8 | 0.67223041203149404461512935128826653E-01 9 | 0.44185506329862696502069589276343558E+00 10 | 0.87009876131956772613858095886641282E+00 11 | ]; 12 | ws0{ 2} = [ 13 | 0.31762944270798476372490954384251290E+00 14 | 0.47075746444480766415735666827990423E+00 15 | 0.21161309284720757211773378787758278E+00 16 | 0.21161309284720757211773378787758306E+00 17 | 0.47075746444480766415735666827990529E+00 18 | 0.31762944270798476372490954384251329E+00 19 | ]; 20 | xs0{ 3} = [ 21 | -.85298066355196672454383075911624428E+00 22 | -.32124197978390065123043035562976512E+00 23 | 0.31445748077201277907785382011839898E+00 24 | 0.72493630770334313159907460618682967E+00 25 | 0.82972082130767210781003589349471502E+00 26 | 0.94914972964885753178755557621486876E+00 27 | ]; 28 | ws0{ 3} = [ 29 | 0.36563174832551892596722547271104100E+00 30 | 0.64396732577704244068727209026149442E+00 31 | 0.56926856752891723455949176838264665E+00 32 | 0.22150998055863719488322208314915615E+00 33 | 0.86384135765238134361132066236308032E-01 34 | 0.11323824204464606954165651925937975E+00 35 | ]; 36 | xs0{ 1} = [ 37 | 0.85298066355196672454383075911624428E+00 38 | 0.32124197978390065123043035562976512E+00 39 | -.31445748077201277907785382011839898E+00 40 | -.72493630770334313159907460618682967E+00 41 | -.82972082130767210781003589349471502E+00 42 | -.94914972964885753178755557621486876E+00 43 | ]; 44 | ws0{ 1} = [ 45 | 0.36563174832551892596722547271104100E+00 46 | 0.64396732577704244068727209026149442E+00 47 | 0.56926856752891723455949176838264665E+00 48 | 0.22150998055863719488322208314915615E+00 49 | 0.86384135765238134361132066236308032E-01 50 | 0.11323824204464606954165651925937975E+00 51 | ]; 52 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/hqsupp_nnode001_npoly002.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = hqsupp_nnode001_npoly002() 2 | xs0 = cell( 1,1); 3 | ws0 = cell( 1,1); 4 | xs0{ 1} = [ 5 | -.39021169606396825495153935800135852E+00 6 | 0.79384539051302290615351549765250396E-01 7 | 0.23175104705465428376862752542177512E+00 8 | 0.75144000798208693575457987189466583E+00 9 | ]; 10 | ws0{ 1} = [ 11 | 0.95781216530792264883208189896560358E+00 12 | -.17323690400943302832555528369457516E+00 13 | 0.10117916168666548753268745403809136E+01 14 | 0.20363312183485550416659884434805796E+00 15 | ]; 16 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/hqsupp_nnode002_npoly004.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = hqsupp_nnode002_npoly004() 2 | xs0 = cell( 2,1); 3 | ws0 = cell( 2,1); 4 | xs0{ 1} = [ 5 | -.89018677908910660463189003294432590E+00 6 | -.62870693768375495808309609585526882E+00 7 | -.58464825915187138698880412714446674E+00 8 | -.47799194632563004934063903137707996E+00 9 | 0.93742857272706347732652393454913630E-01 10 | 0.78358672098522799016949945645681306E+00 11 | ]; 12 | ws0{ 1} = [ 13 | 0.25055978107570433593066567783447396E+00 14 | 0.17212370388827705426846696190976309E+00 15 | -.55985185826108120360462096645293793E-02 16 | 0.31958648966723507430961642561912063E+00 17 | 0.73810977053556049965269099996670659E+00 18 | 0.52521877341583384787460614433446505E+00 19 | ]; 20 | xs0{ 2} = [ 21 | 0.89018677908910660463189003294432590E+00 22 | 0.62870693768375495808309609585526882E+00 23 | 0.58464825915187138698880412714446674E+00 24 | 0.47799194632563004934063903137707996E+00 25 | -.93742857272706347732652393454913630E-01 26 | -.78358672098522799016949945645681306E+00 27 | ]; 28 | ws0{ 2} = [ 29 | 0.25055978107570433593066567783447396E+00 30 | 0.17212370388827705426846696190976309E+00 31 | -.55985185826108120360462096645293793E-02 32 | 0.31958648966723507430961642561912063E+00 33 | 0.73810977053556049965269099996670659E+00 34 | 0.52521877341583384787460614433446505E+00 35 | ]; 36 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/hsupp_nnode001_npoly002.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = hqsupp_nnode001_npoly002() 2 | xs0 = cell( 1,1); 3 | ws0 = cell( 1,1); 4 | xs0{ 1} = [ 5 | -.36787944117144232159552377016146087E+00 6 | 0.36787944117144232159552377016146087E+00 7 | ]; 8 | ws0{ 1} = [ 9 | 0.10000000000000000000000000000000000E+01 10 | 0.10000000000000000000000000000000000E+01 11 | ]; 12 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/hsupp_nnode002_npoly004.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = hqsupp_nnode002_npoly004() 2 | xs0 = cell( 2,1); 3 | ws0 = cell( 2,1); 4 | xs0{ 1} = [ 5 | -.87214237182462656743035766524926372E+00 6 | -.62657518300009868047978534980564034E+00 7 | -.44715260810775101717874641157301103E+00 8 | 0.30184305437039722201185635414518198E+00 9 | 0.93749222463882029786125395671712974E+00 10 | ]; 11 | ws0{ 1} = [ 12 | 0.26901968791805804540228502019545220E+00 13 | 0.12344182694337661450832211530914543E+00 14 | 0.46460497246422954483325372169291894E+00 15 | 0.86804628724021136618942132573404333E+00 16 | 0.27488722543412442906671781706844010E+00 17 | ]; 18 | xs0{ 2} = [ 19 | 0.87214237182462656743035766524926372E+00 20 | 0.62657518300009868047978534980564034E+00 21 | 0.44715260810775101717874641157301103E+00 22 | -.30184305437039722201185635414518198E+00 23 | -.93749222463882029786125395671712974E+00 24 | ]; 25 | ws0{ 2} = [ 26 | 0.26901968791805804540228502019545220E+00 27 | 0.12344182694337661450832211530914543E+00 28 | 0.46460497246422954483325372169291894E+00 29 | 0.86804628724021136618942132573404333E+00 30 | 0.27488722543412442906671781706844010E+00 31 | ]; 32 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/hsupp_nnode003_npoly006.m: -------------------------------------------------------------------------------- 1 | function [xs0,ws0] = hqsupp_nnode003_npoly006() 2 | xs0 = cell( 3,1); 3 | ws0 = cell( 3,1); 4 | xs0{ 1} = [ 5 | -.98034331906557962724935327264428818E+00 6 | -.91161306812567341653150601633223319E+00 7 | -.80079220477220051264217693685520979E+00 8 | -.71401539380985529131786515812037421E+00 9 | -.30729840502445122557608447903370616E+00 10 | 0.32444956747966495880015463251196364E+00 11 | 0.85360948408502256518722727179723580E+00 12 | ]; 13 | ws0{ 1} = [ 14 | 0.39029965429596643818666457904362140E-01 15 | 0.10859234917152833616676497764413228E+00 16 | 0.66505923161676576510124007360625275E-01 17 | 0.21620170066231842706000583949290439E+00 18 | 0.56513322578618926815782507238612259E+00 19 | 0.64050938640733477695069411197545006E+00 20 | 0.36402744938135597133591953323640327E+00 21 | ]; 22 | xs0{ 2} = [ 23 | -.87009876131956772613858095884957239E+00 24 | -.44185506329862696502069589269299570E+00 25 | -.67223041203149404461512935032127902E-01 26 | 0.67223041203149404461512935032127902E-01 27 | 0.44185506329862696502069589269299570E+00 28 | 0.87009876131956772613858095884957239E+00 29 | ]; 30 | ws0{ 2} = [ 31 | 0.31762944270798476372490954388342687E+00 32 | 0.47075746444480766415735666833534588E+00 33 | 0.21161309284720757211773378778122725E+00 34 | 0.21161309284720757211773378778122725E+00 35 | 0.47075746444480766415735666833534588E+00 36 | 0.31762944270798476372490954388342687E+00 37 | ]; 38 | xs0{ 3} = [ 39 | 0.98034331906557962724935327264428818E+00 40 | 0.91161306812567341653150601633223319E+00 41 | 0.80079220477220051264217693685520979E+00 42 | 0.71401539380985529131786515812037421E+00 43 | 0.30729840502445122557608447903370616E+00 44 | -.32444956747966495880015463251196364E+00 45 | -.85360948408502256518722727179723580E+00 46 | ]; 47 | ws0{ 3} = [ 48 | 0.39029965429596643818666457904362140E-01 49 | 0.10859234917152833616676497764413228E+00 50 | 0.66505923161676576510124007360625275E-01 51 | 0.21620170066231842706000583949290439E+00 52 | 0.56513322578618926815782507238612259E+00 53 | 0.64050938640733477695069411197545006E+00 54 | 0.36402744938135597133591953323640327E+00 55 | ]; 56 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/logavail.m: -------------------------------------------------------------------------------- 1 | function iords = logavail() 2 | 3 | filename= '+chnk/+quadggq/logwhts.mat'; 4 | 5 | persistent whts_dict 6 | if isempty(whts_dict) 7 | load(filename,'whts_dict'); 8 | assert(~isempty(whts_dict),'failed to load!') 9 | end 10 | 11 | iords = cell2mat(keys(whts_dict)); 12 | 13 | end 14 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/logwhts.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/+chnk/+quadggq/logwhts.mat -------------------------------------------------------------------------------- /chunkie/+chnk/+quadggq/setuplogquad.m: -------------------------------------------------------------------------------- 1 | function [logquad]=setuplogquad(k,opdims) 2 | % obtain quadrature nodes and weights, and interpolation matrices for 3 | % logarithmic and nearly logarithmic singularities 4 | 5 | msg = "chnk.quadggq.setuplogquad to be deprecated. " + ... 6 | "use chnk.quadggq.setup instead"; 7 | warning(msg); 8 | 9 | npolyfac=2; 10 | [xs1,wts1,xs0,wts0] = chnk.quadggq.getlogquad(k,npolyfac); 11 | ainterp1 = lege.matrin(k,xs1); 12 | temp = eye(opdims(2)); 13 | ainterp1kron = kron(ainterp1,temp); 14 | 15 | nquad0 = size(xs0,1); 16 | 17 | ainterps0kron = cell(k,1); 18 | ainterps0 = cell(k,1); 19 | 20 | for j = 1:k 21 | xs0j = xs0{j}; 22 | ainterp0_sm = lege.matrin(k,xs0j); 23 | ainterps0{j} = ainterp0_sm; 24 | ainterps0kron{j} = kron(ainterp0_sm,temp); 25 | end 26 | 27 | logquad = []; 28 | logquad.xs1 = xs1; 29 | logquad.wts1 = wts1; 30 | logquad.xs0 = xs0; 31 | logquad.wts0 = wts0; 32 | logquad.ainterp1 = ainterp1; 33 | logquad.ainterp1kron = ainterp1kron; 34 | logquad.ainterps0 = ainterps0; 35 | logquad.ainterps0kron = ainterps0kron; 36 | 37 | -------------------------------------------------------------------------------- /chunkie/+chnk/+quadnative/buildmat.m: -------------------------------------------------------------------------------- 1 | function submat = buildmat(chnkr,kern,opdims,i,j,wts) 2 | %CHNK.QUADSMOOTH.BUILDMAT build matrix for far interactions with this kernel 3 | % assuming that the smooth rule is sufficient 4 | % 5 | % 6 | 7 | 8 | if nargin < 4 9 | i = 1:chnkr.nch; 10 | end 11 | if nargin < 5 12 | j = 1:chnkr.nch; 13 | end 14 | 15 | if nargin < 6 16 | [~,wts] = lege.exps(chnkr.k); 17 | end 18 | 19 | % grab specific boundary data 20 | 21 | r = chnkr.rstor; 22 | d = chnkr.dstor; 23 | d2 = chnkr.d2stor; 24 | n = chnkr.nstor; 25 | data = chnkr.datastor; 26 | 27 | [dim,k,~] = size(r); 28 | rs = r(:,:,j); rt = r(:,:,i); ds = d(:,:,j); dt = d(:,:,i); nt = n(:,:,i); 29 | ns = n(:,:,j); 30 | d2s = d2(:,:,j); d2t = d2(:,:,i); 31 | rs = reshape(rs,dim,k*length(j)); rt = reshape(rt,dim,k*length(i)); 32 | ds = reshape(ds,dim,k*length(j)); dt = reshape(dt,dim,k*length(i)); 33 | d2s = reshape(d2s,dim,k*length(j)); d2t = reshape(d2t,dim,k*length(i)); 34 | 35 | srcinfo = []; srcinfo.r = rs; srcinfo.d = ds; srcinfo.d2 = d2s; srcinfo.n = ns; 36 | targinfo = []; targinfo.r = rt; targinfo.d = dt; targinfo.d2 = d2t; targinfo.n = nt; 37 | 38 | if (not (isempty(data))) 39 | srcinfo.data = data(:,:,j); 40 | targinfo.data = data(:,:,i); 41 | end 42 | 43 | dsnrms = sqrt(sum(ds.^2,1)); 44 | ws = repmat(wts(:),length(j),1); 45 | 46 | dsdt = dsnrms(:).*ws; 47 | 48 | dsdtndim2 = repmat(dsdt(:).',opdims(2),1); 49 | dsdtndim2 = dsdtndim2(:); 50 | 51 | submat = bsxfun(@times,kern(srcinfo,targinfo),(dsdtndim2(:)).'); 52 | 53 | end 54 | -------------------------------------------------------------------------------- /chunkie/+chnk/+rcip/IPinit.m: -------------------------------------------------------------------------------- 1 | function [IP,IPW]=IPinit(T,W) 2 | %CHNK.RCIP.IPinit 3 | % 4 | % construct the prolongation matrix IP that maps function values 5 | % on n_{gl} Gauss-Legendre nodes on [-1,1] to function values at 6 | % 2n_{gl} Gauss-Legendre, with shifted and scaled n_{gl} 7 | % Gauss-Legendre nodes on each subinterval [-1,0], [0,1], respectively. 8 | % 9 | % IPW is the weighted prolongation matrix acted on the left side. 10 | % 11 | 12 | % author: Johan Helsing (part of RCIP tutorial) 13 | 14 | ngl = length(T); 15 | A=ones(ngl); 16 | AA=ones(2*ngl,ngl); 17 | T2=[T-1;T+1]/2; 18 | W2=[W;W]/2; 19 | for k=2:ngl 20 | A(:,k)=A(:,k-1).*T; 21 | AA(:,k)=AA(:,k-1).*T2; 22 | end 23 | IP=AA/A; 24 | IPW=IP.*(W2*(1./W)'); -------------------------------------------------------------------------------- /chunkie/+chnk/+rcip/Pbcinit.m: -------------------------------------------------------------------------------- 1 | function Pbc=Pbcinit(IP,nedge,ndim) 2 | %CHNK.RCIP.Pbcinit 3 | % 4 | % construct the nontrivial part of the prolongation matrix for the whole 5 | % system. Suppose that nedge is the number of edges meeting at the 6 | % corner, ndim is the number of equations, n_{gl} is the number of 7 | % Gauss-Legendre nodes on each chunk. Then Pbc is a block diagonal 8 | % matrix with nedge diagonal blocks, where each block is of the size 9 | % 2n_{gl} \times n_{gl} 10 | 11 | % Pbc=kron(eye(nedge*ndim),IP); % the other order - one big block after 12 | % another 13 | 14 | % author: Johan Helsing (part of the RCIP tutorial) 15 | Pbc=kron(eye(nedge),kron(IP,eye(ndim))); 16 | -------------------------------------------------------------------------------- /chunkie/+chnk/+rcip/shiftedlegbasismats.m: -------------------------------------------------------------------------------- 1 | function [sbclmat,sbcrmat,leftvalmat,rightvalmat,u] = shiftedlegbasismats(k) 2 | %shiftedlegbasismats 3 | % 4 | % utility for rcip. not designed for end-user 5 | % 6 | % input 7 | % k - legendre node order on chunk 8 | % 9 | % output 10 | % sbclmat - matrix from function values at legendre 11 | % nodes scaled to [0,1] to expansion 12 | % of the form t*\sum_{j=0}^{k-1} c_j P_j(2t-1) 13 | % sbcrmat - matrix from function values at legendre 14 | % nodes scaled to [-1,0] to expansion 15 | % of the form t*\sum_{j=0}^{k-1} c_j P_j(2t+1) 16 | % leftvalmat - matrix from function values to value of 17 | % interpolant at left end 18 | % 19 | 20 | % author: Travis Askham 21 | 22 | [t0,~,u,v] = lege.exps(k); 23 | 24 | t = (t0+1)/2; 25 | basis = t(:).*v(:,1:end-1); 26 | [uu,ss,vv] = svd(basis); 27 | 28 | sbclmat = vv(:,1:k-1)*(ss(1:k-1,1:k-1)\(uu(:,1:k-1)')); 29 | 30 | t = (t0-1)/2; 31 | basis = t(:).*v(:,1:end-1); 32 | [uu,ss,vv] = svd(basis); 33 | 34 | sbcrmat = vv(:,1:k-1)*(ss(1:k-1,1:k-1)\(uu(:,1:k-1)')); 35 | 36 | pm1 = lege.pols(-1,k-1); 37 | leftvalmat = (pm1(:).')*u; 38 | 39 | p1 = lege.pols(1,k-1); 40 | rightvalmat = (p1(:).')*u; 41 | 42 | end 43 | -------------------------------------------------------------------------------- /chunkie/+chnk/+smoother/expeval.m: -------------------------------------------------------------------------------- 1 | function [cvals] = expeval(czs,ifexps) 2 | 3 | sz = size(czs); 4 | czs = czs(:); 5 | cvals= zeros(size(czs)); 6 | 7 | ifloc = find(abs(czs) <= 2); 8 | iffar = find(abs(czs) >2); 9 | 10 | if (numel(ifloc)) 11 | cloc = expeval_tayl(czs(ifloc)); 12 | cvals(ifloc) = cloc; 13 | end 14 | if (numel(iffar)>0) 15 | cfar = expeval_lentz(czs(iffar)); 16 | cvals(iffar) = cfar; 17 | end 18 | 19 | if ((nargin>1) && ifexps) 20 | cvals = cvals.*exp(-czs); 21 | end 22 | 23 | cvals = reshape(cvals,sz); 24 | 25 | end 26 | 27 | 28 | function [cvals] = expeval_tayl(czs) 29 | 30 | gamma = 0.577215664901532860606512090082; 31 | 32 | cvals = -gamma-log(czs); 33 | cpow = czs; 34 | rfac = 1; 35 | 36 | eps = 1E-24; 37 | 38 | for ii=1:31 39 | cvals = cvals+cpow.*rfac/ii; 40 | cpow = -czs.*cpow; 41 | rfac = rfac/(ii+1); 42 | % if (max(abs(cpow.*rfac)) < eps) 43 | % break; 44 | % end 45 | end 46 | 47 | cvals = cvals.*exp(czs); 48 | 49 | end 50 | 51 | 52 | function [cvals] = expeval_lentz(czs) 53 | 54 | nterms = 40; 55 | cf = 1./czs; 56 | cd = cf; 57 | cv = 1/1E-30; 58 | 59 | for ii=1:80 60 | can = ii; 61 | cd = 1./(1+ii*cd); 62 | cv = 1 + ii./cv; 63 | del = cd.*cv; 64 | cf = cf.*del; 65 | cd = 1./(czs+ii*cd); 66 | cv = czs + ii./cv; 67 | del = cd.*cv; 68 | cf = cf.*del; 69 | % if (max(abs(del-1)) < 1E-14) 70 | % break; 71 | % end 72 | end 73 | 74 | cvals = cf; 75 | 76 | end 77 | -------------------------------------------------------------------------------- /chunkie/+chnk/+smoother/get_mesh.m: -------------------------------------------------------------------------------- 1 | function qmesh = get_mesh(umesh, nchs, k) 2 | [x, w] = lege.exps(k); 3 | 4 | nchtot = sum(nchs(:)); 5 | n = nchtot*k; 6 | qmesh.r = zeros(2,n); 7 | qmesh.n = zeros(2,n); 8 | qmesh.pseudo_normals = zeros(2,n); 9 | qmesh.wts = zeros(n,1); 10 | 11 | [~, ne] = size(umesh.verts); 12 | verts_ext = [umesh.verts, umesh.verts(:,1)]; 13 | pseudo_normals_ext = [umesh.pseudo_normals, umesh.pseudo_normals(:,1)]; 14 | istart = 1; 15 | for i=1:ne 16 | [xext, wext] = get_nodes(x, w, nchs(i)); 17 | ll = length(xext); 18 | iend = istart+ll-1; 19 | qmesh.r(:,istart:iend) = verts_ext(:,i) + ... 20 | (verts_ext(:,i+1) - verts_ext(:,i)).*xext.'; 21 | qmesh.n(:,istart:iend) = repmat(umesh.face_normals(:,i),[1,ll]); 22 | qmesh.pseudo_normals(:,istart:iend) = ... 23 | repmat(umesh.pseudo_normals(:,i), [1,ll]) + ... 24 | (pseudo_normals_ext(:,i+1) - pseudo_normals_ext(:,i)).*xext.'; 25 | qmesh.wts(istart:iend) = wext.*umesh.lengths(i); 26 | istart = istart + ll; 27 | end 28 | 29 | end 30 | 31 | 32 | function [xext, wext] = get_nodes(x, w, nch) 33 | tabs = 0:1/nch:1; 34 | tas = tabs(1:nch); 35 | tbs = tabs(2:end); 36 | xext = (x(:)+1)/2.*(tbs - tas) + tas; 37 | xext = xext(:); 38 | wext = w(:)/2.*(tbs-tas); 39 | wext = wext(:); 40 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+smoother/get_sigs.m: -------------------------------------------------------------------------------- 1 | function [val,grad] = get_sigs(umesh,rt,sig0,dlam) 2 | 3 | rc = umesh.centroids; 4 | dlens = umesh.lengths; 5 | 6 | [~,ns] = size(rc); 7 | [~,nt] = size(rt); 8 | 9 | xc = repmat(rc(1,:),nt,1); 10 | yc = repmat(rc(2,:),nt,1); 11 | dl = repmat(dlens,nt,1); 12 | 13 | xt = repmat(rt(1,:).',1,ns); 14 | yt = repmat(rt(2,:).',1,ns); 15 | 16 | dx = xt-xc; 17 | dy = yt-yc; 18 | dr = sqrt(dx.^2+dy.^2); 19 | dmin = min(dr,[],2); 20 | 21 | dsigj = dl/dlam; 22 | dexpn = exp(-(dr.^2-dmin.^2)./(2*sig0^2)); 23 | dsignum = sum(dsigj.*dexpn,2); 24 | dsigden = sum(dexpn,2); 25 | dsignumx = -sum(dsigj.*dexpn.*(dx./sig0^2),2); 26 | dsignumy = -sum(dsigj.*dexpn.*(dy./sig0^2),2); 27 | dsig = dsignum./dsigden; 28 | dsigx = dsignumx./dsigden; 29 | dsigy = dsignumy./dsigden; 30 | 31 | val = dsig; 32 | 33 | sz = size(dsig); 34 | grad = zeros([sz,2]); 35 | grad(:,:,1) = dsigx; 36 | grad(:,:,2) = dsigy; 37 | 38 | grad = squeeze(grad); 39 | 40 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+smoother/get_umesh.m: -------------------------------------------------------------------------------- 1 | function [umesh] = get_umesh(verts) 2 | umesh = []; 3 | umesh.verts = verts; 4 | [~, nv] = size(verts); 5 | verts_ext = [verts, verts(:,1)]; 6 | d = verts_ext(:,2:end) - verts_ext(:,1:nv); 7 | umesh.centroids = 0.5*(verts_ext(:,2:end) + verts_ext(:,1:nv)); 8 | dd = sqrt(sum(d.^2, 1)); 9 | umesh.lengths = dd; 10 | face_normals = zeros(2,nv); 11 | face_normals(1,:) = d(2,:)./dd; 12 | face_normals(2,:) = -d(1,:)./dd; 13 | 14 | umesh.face_normals = face_normals; 15 | face_normals_ext = [face_normals(:,end), face_normals]; 16 | pseudo_normals = 0.5*(face_normals_ext(:,2:end) + ... 17 | face_normals_ext(:,1:nv)); 18 | dd = sqrt(sum(pseudo_normals.^2, 1)); 19 | pseudo_normals = pseudo_normals./dd; 20 | 21 | umesh.pseudo_normals = pseudo_normals; 22 | 23 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+smoother/gpsi_all.m: -------------------------------------------------------------------------------- 1 | function [val,grad,hess,hess_sig] = gpsi_all(dx,dy,dr,dsigt) 2 | 3 | [val,vald] = chnk.smoother.psi_eval(dr,dsigt); 4 | 5 | da = 1/(4*pi); 6 | z = dr.^2./(2*dsigt.*dsigt); 7 | val = val + log(z)*da; 8 | 9 | if (nargout==1) 10 | return 11 | end 12 | 13 | grad = zeros(numel(dx),2); 14 | grad(:,1) = vald.*dx./dr; 15 | grad(:,2) = vald.*dy./dr; 16 | 17 | grad(:,1) = grad(:,1)+2*dx./(dr.*dr)*da; 18 | grad(:,2) = grad(:,2)+2*dy./(dr.*dr)*da; 19 | 20 | if (nargout==2) 21 | return 22 | end 23 | 24 | hess = zeros(numel(dx),2,2); 25 | 26 | hess(:,1,1) = 0; 27 | hess(:,1,2) = 0; 28 | hess(:,2,1) = 0; 29 | hess(:,2,2) = 0; 30 | 31 | eterm = exp(-dr.*dr./(2*dsigt.^2)); 32 | 33 | hess(:,1,1) = eterm./(dr.*dr); 34 | hess(:,2,2) = eterm./(dr.*dr); 35 | 36 | fact = -(2*dsigt.^2+dr.^2)./(dsigt.^2.*dr.^2).*eterm; 37 | hess(:,1,1) = hess(:,1,1) + (dx.*dx./dr.^2).*fact; 38 | hess(:,1,2) = hess(:,1,2) + (dx.*dy./dr.^2).*fact; 39 | hess(:,2,1) = hess(:,2,1) + (dx.*dy./dr.^2).*fact; 40 | hess(:,2,2) = hess(:,2,2) + (dy.*dy./dr.^2).*fact; 41 | 42 | hess(:,1,1) = hess(:,1,1)/(2*pi); 43 | hess(:,2,1) = hess(:,2,1)/(2*pi); 44 | hess(:,1,2) = hess(:,1,2)/(2*pi); 45 | hess(:,2,2) = hess(:,2,2)/(2*pi); 46 | 47 | hess(:,1,1) = hess(:,1,1) - 2./(dr.*dr)*da; 48 | hess(:,2,2) = hess(:,2,2) - 2./(dr.*dr)*da; 49 | 50 | fact = da*4./dr.^4; 51 | hess(:,1,1) = hess(:,1,1) + dx.*dx.*fact; 52 | hess(:,1,2) = hess(:,1,2) + dx.*dy.*fact; 53 | hess(:,2,1) = hess(:,2,1) + dx.*dy.*fact; 54 | hess(:,2,2) = hess(:,2,2) + dy.*dy.*fact; 55 | 56 | if (nargout==3) 57 | return 58 | end 59 | 60 | 61 | fact = eterm./(dsigt.^3)/(2*pi); 62 | hess_sig(:,1) = -dx.*fact; 63 | hess_sig(:,2) = -dy.*fact; 64 | 65 | end 66 | -------------------------------------------------------------------------------- /chunkie/+chnk/+smoother/gpsi_loc.m: -------------------------------------------------------------------------------- 1 | function [val,grad,hess,hess_sig] = gpsi_loc(dx,dy,dr,dsigt) 2 | 3 | degam = 0.57721566490153286060651209008240243104; 4 | da = sqrt(2)*dsigt; 5 | z = dr./da; 6 | z2 = z.*z; 7 | val = (z2-z2.^2/4+z2.^3/18-z2.^4/96+z2.^5/600-z2.^6/4320); 8 | val = val./(4*pi); 9 | val = val - degam/(4*pi); 10 | 11 | if (nargout==1) 12 | return 13 | end 14 | 15 | grad = zeros(numel(dx),2); 16 | vvd = (1-z2/2+z2.^2/6-z2.^3/24+z2.^4/120-z2.^5/720); 17 | grad(:,1) = dx.*vvd./(2*pi*da.^2); 18 | grad(:,2) = dy.*vvd./(2*pi*da.^2); 19 | 20 | if (nargout==2) 21 | return 22 | end 23 | 24 | hess = zeros(numel(dx),2,2); 25 | hess(:,1,1) = -vvd./(2*pi*da.^2); 26 | hess(:,2,2) = -vvd./(2*pi*da.^2); 27 | hess(:,1,2) = 0; 28 | hess(:,2,1) = 0; 29 | 30 | vvvd = (-1+4*z2/6-6*z2.^2/24+8*z2.^3/120-10*z2.^4/720); 31 | vvvd = -vvvd./(2*pi*da.^2)./da./da; 32 | hess(:,1,1) = hess(:,1,1) + dx.*dx.*vvvd; 33 | hess(:,2,2) = hess(:,2,2) + dy.*dy.*vvvd; 34 | hess(:,1,2) = hess(:,1,2) + dx.*dy.*vvvd; 35 | hess(:,2,1) = hess(:,2,1) + dx.*dy.*vvvd; 36 | 37 | if (nargout==3) 38 | return 39 | end 40 | 41 | hess_sig = zeros(numel(dx),2); 42 | 43 | eterm = exp(-dr.*dr./(2*dsigt.^2)); 44 | fact = eterm./(dsigt.^3)/(2*pi); 45 | hess_sig(:,1) = -dx.*fact; 46 | hess_sig(:,2) = -dy.*fact; 47 | 48 | end 49 | -------------------------------------------------------------------------------- /chunkie/+chnk/+smoother/green.m: -------------------------------------------------------------------------------- 1 | function [val,grad,hess,hess_sig] = green(rs,rt,dsigt) 2 | 3 | [~,ns] = size(rs); 4 | [~,nt] = size(rt); 5 | 6 | xs = repmat(rs(1,:),nt,1); 7 | ys = repmat(rs(2,:),nt,1); 8 | 9 | xt = repmat(rt(1,:).',1,ns); 10 | yt = repmat(rt(2,:).',1,ns); 11 | dst = repmat(dsigt.',1,ns); 12 | 13 | dx = xt-xs; 14 | dy = yt-ys; 15 | dr = sqrt(dx.^2+dy.^2); 16 | 17 | sz = size(dx); 18 | dx = dx(:); 19 | dy = dy(:); 20 | dr = dr(:); 21 | dst = dst(:); 22 | 23 | da = sqrt(2.0d0)*dst; 24 | z = dr./da; 25 | 26 | iloc = find(z < 0.1); 27 | ifar = find(z >= 0.1); 28 | 29 | vs = zeros(ns*nt,1); 30 | gs = zeros(ns*nt,2); 31 | hs = zeros(ns*nt,2,2); 32 | hsigs = zeros(ns*nt,2); 33 | 34 | if (numel(iloc) ~=0) 35 | [vl,gl,hl,hsl] = chnk.smoother.gpsi_loc(dx(iloc), dy(iloc), ... 36 | dr(iloc), dst(iloc)); 37 | vs(iloc) = vl; 38 | gs(iloc,:) = gl; 39 | hs(iloc,:,:) = hl; 40 | hsigs(iloc,:) = hsl; 41 | end 42 | if (numel(ifar) ~=0) 43 | [vf,gf,hf,hsf] = chnk.smoother.gpsi_all(dx(ifar), dy(ifar), ... 44 | dr(ifar), dst(ifar)); 45 | vs(ifar) = vf; 46 | gs(ifar,:) = gf; 47 | hs(ifar,:,:) = hf; 48 | hsigs(ifar,:) = hsf; 49 | end 50 | 51 | val = reshape(vs,sz); 52 | if (nargout > 1) 53 | grad = squeeze(reshape(gs,[sz,2])); 54 | end 55 | if (nargout > 2) 56 | hess = squeeze(reshape(hs,[sz,2,2])); 57 | end 58 | if (nargout > 3) 59 | hess_sig = squeeze(reshape(hsigs,[sz,2])); 60 | end 61 | 62 | end 63 | -------------------------------------------------------------------------------- /chunkie/+chnk/+smoother/newt_step.m: -------------------------------------------------------------------------------- 1 | function [h,varargout] = newt_step(h,umesh,dmesh,qmesh,sig0,lam,opts) 2 | 3 | level = 0.5; 4 | step_fact = 1; 5 | ww = qmesh.wts(:).'; 6 | 7 | if (nargin > 6) 8 | if (isfield(opts,"levels")) 9 | level = opts.levels; 10 | end 11 | 12 | if (isfield(opts,"scales")) 13 | ww = ww.*opts.scales.'; 14 | end 15 | 16 | if (isfield(opts,"step_fact")) 17 | step_fact = opts.step_fact; 18 | end 19 | end 20 | 21 | dpx = dmesh.pseudo_normals(1,:).'; 22 | dpy = dmesh.pseudo_normals(2,:).'; 23 | 24 | rnx = qmesh.n(1,:).'; 25 | rny = qmesh.n(2,:).'; 26 | 27 | rt = dmesh.r; 28 | rt(1,:) = rt(1,:) + (h.*dpx).'; 29 | rt(2,:) = rt(2,:) + (h.*dpy).'; 30 | 31 | [sig, sig_grad] = chnk.smoother.get_sigs(umesh, rt, sig0, lam); 32 | [val, grad, hess, hess_sig] = chnk.smoother.green(qmesh.r, rt, sig); 33 | gx = grad(:,:,1); 34 | gy = grad(:,:,2); 35 | 36 | phi = -(gx*(rnx.*ww.') + gy*(rny.*ww.')) - level; 37 | 38 | 39 | h11 = hess(:,:,1,1).*ww; 40 | h12 = hess(:,:,1,2).*ww; 41 | h21 = hess(:,:,2,1).*ww; 42 | h22 = hess(:,:,2,2).*ww; 43 | 44 | h1sig = hess_sig(:,:,1).*ww; 45 | h2sig = hess_sig(:,:,2).*ww; 46 | 47 | dx1 = h11*rnx + h12*rny; 48 | dy1 = h21*rnx + h22*rny; 49 | 50 | dx2 = h1sig*rnx + h2sig*rny; 51 | dy2 = dx2; 52 | 53 | dsigx = sig_grad(:,1); 54 | dsigy = sig_grad(:,2); 55 | 56 | dx2 = dx2.*dsigx; 57 | dy2 = dy2.*dsigy; 58 | 59 | 60 | dphidh = (dx1 + dx2).*dpx + (dy1 + dy2).*dpy; 61 | h = h - step_fact*phi./dphidh; 62 | 63 | if (nargout > 1) 64 | varargout{1} = max(abs(phi(:))); 65 | end 66 | if (nargout > 2) 67 | varargout{2} = abs(phi(:)); 68 | end 69 | end -------------------------------------------------------------------------------- /chunkie/+chnk/+smoother/psi_eval.m: -------------------------------------------------------------------------------- 1 | function [val,vald] = psi_eval(x,dsig) 2 | z = x.*x./(2*dsig.*dsig); 3 | vexp = chnk.smoother.expeval(z,1); 4 | val = vexp/(4*pi); 5 | vald = -exp(-z)./(2*pi*x); 6 | end 7 | -------------------------------------------------------------------------------- /chunkie/+chnk/+spcl/absconvgauss.m: -------------------------------------------------------------------------------- 1 | function [val, der, der2] = absconvgauss(x, a, b, h) 2 | %ABSCONVGAUSS this routine computes the convolution% 3 | % ( a*abs(x)+b ) \star 1/(sqrt(2*pi)*h^2) exp(-x^2/(2*h^2)) 4 | % 5 | % this effectively smoothes off the corner from the abs(x) function 6 | % 7 | % 8 | 9 | x2=x/sqrt(2.0)/h; 10 | verf = erf(x2); 11 | val=a*x.*verf+sqrt(2.0/pi)*a*h*exp(-x.*x/2.0/h/h)+b; 12 | % 13 | if nargout > 1; der=a*verf; end 14 | if nargout > 2; der2=a*sqrt(2.0/pi)/h*exp(-x.*x/2.0/h/h); end 15 | % 16 | end 17 | -------------------------------------------------------------------------------- /chunkie/+chnk/curvature2d.m: -------------------------------------------------------------------------------- 1 | function kappa = curvature2d(ptinfo) 2 | %CHNK.CURVATURE2D signed curvature of points on 2D curve 3 | % 4 | % kappa = (x'y''-x''y')/( sqrt(x'^2+y'^2)^3 ) 5 | % 6 | % Syntax: kappa = chnk.curvature2d(ptinfo) 7 | % 8 | % Input: 9 | % ptinfo - curve point info struct, with entries 10 | % ptinfo.r - positions (2,:) array 11 | % ptinfo.d - first derivative in underlying parameterization (2,:) 12 | % ptinfo.d2 - second derivative in underlying parameterization (2,:) 13 | % 14 | % Output: 15 | % nrm - (2,:) array containing corresponding normal information 16 | % 17 | % see also CHNK.NORMAL2D 18 | 19 | d = ptinfo.d; 20 | sh = size(d); sh = sh(2:end); 21 | d2 = ptinfo.d2; 22 | dnrm3 = sqrt(sum(d.^2,1)).^3; 23 | kappa = bsxfun(@rdivide,d(1,:).*d2(2,:)-d(2,:).*d2(1,:),dnrm3(:).'); 24 | if (length(sh) > 1) kappa = reshape(kappa,sh); end -------------------------------------------------------------------------------- /chunkie/+chnk/flagself.m: -------------------------------------------------------------------------------- 1 | function flagslf = flagself(srcs, targs, tol) 2 | % identify sources and targets pairs that are within tol (1e-14); 3 | 4 | % todo: make this more robust by searching for all pairs that are close 5 | % not just the closest 6 | if nargin < 3 7 | tol = 1e-14; 8 | end 9 | 10 | flagslf = []; 11 | 12 | randangle = 2*pi*rand(); 13 | randrot = [cos(randangle), -sin(randangle); ... 14 | sin(randangle), cos(randangle)]; 15 | 16 | srcrot = randrot*srcs(:,:); 17 | targrot = randrot*targs(:,:); 18 | 19 | [srcsortx, jds] = sort(srcrot(1,:)); 20 | [targsortx, ids] = sort(targrot(1,:)); 21 | 22 | binids = cell(length(srcsortx),1); 23 | 24 | idcheck = [1;2]; 25 | for j = 1:length(srcsortx) 26 | while (idcheck(2) < length(targsortx) && ... 27 | targsortx(idcheck(2)) < srcsortx(j)) 28 | idcheck = idcheck+1; 29 | end 30 | [d, kd] = min(abs(targsortx(idcheck) - srcsortx(j))); 31 | idclose = idcheck(kd); 32 | if d < tol 33 | binids{jds(j)} = [binids{jds(j)}, ids(idclose)]; 34 | end 35 | end 36 | 37 | [srcsorty, jds] = sort(srcrot(2,:)); 38 | [targsorty, ids] = sort(targrot(2,:)); 39 | 40 | idcheck = [1;2]; 41 | for j = 1:length(srcsorty) 42 | while (idcheck(2) < length(targsorty) && ... 43 | targsorty(idcheck(2)) < srcsorty(j)) 44 | idcheck = idcheck+1; 45 | end 46 | [d, kd] = min(abs(targsorty(idcheck) - srcsorty(j))); 47 | idclose = idcheck(kd); 48 | if d < tol 49 | if ismember(ids(idclose), binids{jds(j)}) 50 | flagslf = [flagslf, [jds(j);ids(idclose)]]; 51 | end 52 | end 53 | end 54 | if ~isempty(flagslf) 55 | [~, ids] = sort(flagslf(1,:)); 56 | flagslf = flagslf(:,ids); 57 | end 58 | end -------------------------------------------------------------------------------- /chunkie/+chnk/normal2d.m: -------------------------------------------------------------------------------- 1 | function nrm = normal2d(ptinfo) 2 | %CHNK.NORMAL2D normal vector to curve for 2D curves 3 | % 4 | % Syntax: nrm = chnk.normal2d(ptinfo) 5 | % 6 | % Input: 7 | % ptinfo - curve point info struct, with entries 8 | % ptinfo.r - positions (2,:) array 9 | % ptinfo.d - first derivative in underlying parameterization (2,:) 10 | % ptinfo.d2 - second derivative in underlying parameterization (2,:) 11 | % 12 | % Output: 13 | % nrm - (2,:) array containing corresponding normal information 14 | % 15 | % see also CHNK.CURVATURE2D 16 | 17 | nrm = ptinfo.d; 18 | dnrm = sqrt(sum(nrm.^2,1)); 19 | nrm = flipud(nrm); 20 | nrm(2,:) = -nrm(2,:); 21 | nrm = bsxfun(@rdivide,nrm,dnrm); -------------------------------------------------------------------------------- /chunkie/+chnk/perp.m: -------------------------------------------------------------------------------- 1 | function n = perp(tau) 2 | 3 | n = [tau(2,:); -tau(1,:)]; 4 | n = reshape(n,size(tau)); -------------------------------------------------------------------------------- /chunkie/+lege/adapgauss.m: -------------------------------------------------------------------------------- 1 | function [rint,maxrec,numint,ier] = adapgauss(fun,a,b,t,w) 2 | 3 | k = 16; 4 | eps = 1e-12; 5 | 6 | if nargin < 5 7 | [t,w] = lege.exps(k); 8 | end 9 | 10 | nnmax=100000; 11 | maxdepth=200; 12 | 13 | stack = zeros(2,maxdepth); 14 | vals = zeros(maxdepth); 15 | 16 | % start the recursion 17 | 18 | stack(1,1)=a; 19 | stack(2,1)=b; 20 | 21 | vals(1) = oneintp(fun,a,b,t,w); 22 | 23 | % recursively integrate the thing 24 | 25 | j=1; 26 | rint=0; 27 | ier=0; 28 | maxrec=0; 29 | for i=1:nnmax 30 | numint=i; 31 | if(j > maxrec); maxrec=j; end 32 | 33 | % subdivide the current subinterval 34 | 35 | c=(stack(1,j)+stack(2,j))/2; 36 | v2 = oneintp(fun,stack(1,j),c,t,w); 37 | v3 = oneintp(fun,c,stack(2,j),t,w); 38 | 39 | dd= abs(v2+v3-vals(j)); 40 | if(dd <= eps) 41 | 42 | 43 | % if the function on this subinterval has been 44 | % integrated with sufficient accuracy - add the 45 | % value to that of the global integral and move up 46 | % in the stack 47 | 48 | % 49 | rint=rint+v2+v3; 50 | j=j-1; 51 | % 52 | % if the whole thing has been integrated - return 53 | % 54 | if(j == 0); return; end 55 | 56 | else 57 | 58 | % if the function on this subinterval has not been 59 | % integrated with sufficient accuracy - move 60 | % down the stack 61 | 62 | stack(1,j+1)=stack(1,j); 63 | stack(2,j+1)=(stack(1,j)+stack(2,j))/2; 64 | vals(j+1)=v2; 65 | % 66 | stack(1,j)=(stack(1,j)+stack(2,j))/2; 67 | vals(j)=v3; 68 | % 69 | j=j+1; 70 | % 71 | % if the depth of the recursion has become excessive - bomb 72 | % 73 | if(j > maxdepth) 74 | ier = 8; 75 | return; 76 | end 77 | end 78 | end 79 | 80 | ier = 16; 81 | end 82 | 83 | function val = oneintp(fun,a,b,t,w) 84 | % integrate the function fun on the interval [a,b] 85 | 86 | u=(b-a)/2; 87 | v=(b+a)/2; 88 | tt = u*t+v; 89 | ftt = fun(tt); 90 | val = sum(ftt.*w)*u; 91 | end 92 | 93 | -------------------------------------------------------------------------------- /chunkie/+lege/barywts.m: -------------------------------------------------------------------------------- 1 | function w = barywts(k,x) 2 | %LEGE.BARYWTS 3 | % 4 | % returns the weights for barycentric Lagrange interpolation 5 | % for the kth order Legendre nodes 6 | % 7 | % input: 8 | % 9 | % k - the number of Legendre nodes 10 | % 11 | % output: 12 | % 13 | % w - vector of length k such that 14 | % 15 | % w(i) = 1/\prod_{j\neq i} (x(j)-x(i)) 16 | % 17 | % where x(j) is the jth Legendre node of order k 18 | 19 | if nargin < 2 20 | x = lege.exps(k); 21 | end 22 | 23 | xx = bsxfun(@minus,x,x.'); 24 | xx(1:k+1:end) = 1; 25 | 26 | w = prod(xx,1); 27 | w = w(1)./w(:); -------------------------------------------------------------------------------- /chunkie/+lege/bernstein_ellipse.m: -------------------------------------------------------------------------------- 1 | function zell = bernstein_ellipse(ntheta,rho) 2 | 3 | th = linspace(0,2*pi,ntheta+1); 4 | zell = rho*exp(1i*th(1:end-1)); 5 | zell = (zell+1./zell)/2; 6 | zell = zell(:); -------------------------------------------------------------------------------- /chunkie/+lege/dermat.m: -------------------------------------------------------------------------------- 1 | function mat = dermat(k,u,v) 2 | %LEGE.DERMAT returns the spectral differentiation matrix on Legendre nodes 3 | % of order k 4 | % 5 | % input: 6 | % k - integer, number of Legendre nodes 7 | % 8 | % optional inputs: 9 | % u - k x k matrix mapping values at legendre nodes to legendre series 10 | % coefficients 11 | % v - k x k matrix mapping legendre series coefficients to values at 12 | % legendre nodes 13 | % 14 | % output: 15 | % mat - spectral differentiation matrix on Legendre nodes 16 | % 17 | %see also LEGE.EXPS, LEGE.DERPOL 18 | 19 | if nargin < 3 20 | [~,~,u,v] = lege.exps(k); 21 | end 22 | 23 | mat = v(:,1:end-1)*lege.derpol(u); 24 | -------------------------------------------------------------------------------- /chunkie/+lege/derpol.m: -------------------------------------------------------------------------------- 1 | function dercoeffs = derpol(coeffs) 2 | %LEGE.DERPOL compute the coefficients of the derivative 3 | % of the polynomial with the coefficients given on 4 | % input 5 | 6 | sz = size(coeffs); 7 | sz(1)= max(sz(1)-1,0); 8 | n = sz(1); 9 | dercoeffs = zeros(sz); 10 | 11 | if (n<=0); return; end 12 | 13 | pk = coeffs(n+1,:); 14 | pkm1 = coeffs(end-1,:); 15 | pkm2=0; 16 | 17 | for k = n+1:-1:2 18 | j = k-1; 19 | dercoeffs(k-1,:)= pk*(2*j-1); 20 | if(k > 2); pkm2=coeffs(k-2,:)+pk; end 21 | pk=pkm1; 22 | pkm1=pkm2; 23 | end 24 | 25 | end -------------------------------------------------------------------------------- /chunkie/+lege/exev.m: -------------------------------------------------------------------------------- 1 | function val = exev(xs,coeff) 2 | %LEGE.EXEV evaluate legendre expansion with given coeff at points xs 3 | % 4 | % input: 5 | % xs - array of points to evaluate at 6 | % coeff - n times nfun array of coefficients, each column corresponding 7 | % to an (n-1)th order Chebyshev polynomial 8 | % 9 | % output: 10 | % val - size of xs by nfun array of values for each set of coefficients 11 | % evaluated at the points xs (if nfun = 1, we squeeze the output) 12 | 13 | [n,nfun] = size(coeff); 14 | sz = size(xs); 15 | xs = xs(:); 16 | pjm2=ones(length(xs),1); 17 | pjm1=xs; 18 | 19 | val=pjm2*coeff(1,:); 20 | if (n == 1); return; end 21 | val = val + pjm1*coeff(2,:); 22 | if (n == 2); return; end 23 | 24 | for j = 2:(n-1) 25 | pj= ( (2*j-1)*xs.*pjm1-(j-1)*pjm2 ) / j; 26 | val = val+pj*coeff(j+1,:); 27 | pjm2 = pjm1; 28 | pjm1 = pj; 29 | end 30 | 31 | sz2 = sz; 32 | if nfun > 1 33 | sz2 = [sz nfun]; 34 | end 35 | val = squeeze(reshape(val,sz2)); -------------------------------------------------------------------------------- /chunkie/+lege/exps.m: -------------------------------------------------------------------------------- 1 | function [x,w,u,v] = exps(k,opts) 2 | %LEGE.EXPS get nodes, weights, and matrices for switching between values 3 | % and coefficients for Legendre nodes of the specified order 4 | % 5 | % IN: 6 | % k - the desired order (number of points) 7 | % opts - options structure. 8 | % opts.stab (false): if true, force use of slow but more stable 9 | % method for weights and nodes. default false uses linear scaling 10 | % routine which can lose some precision in the weights 11 | % OUT: 12 | % x - k Legendre nodes on [-1,1] 13 | % w - the corresponding integration weights 14 | % u - matrix which maps function values at k Legendre nodes to the 15 | % corresponding coefficients 16 | % v - matrix which evaluates the Legendre polynomial with the given 17 | % coefficients at the k Legendre nodes. 18 | % 19 | stab = false; 20 | if nargin > 1 21 | if isfield(opts,'stab') 22 | stab = opts.stab; 23 | end 24 | end 25 | 26 | if (or(stab,k<=200)) 27 | if nargout > 1 28 | [x,w] = lege.rts_stab(k); 29 | else 30 | x = lege.rts_stab(k); 31 | end 32 | else 33 | if nargout > 1 34 | [x,w] = lege.rts(k); 35 | else 36 | x = lege.rts(k); 37 | end 38 | end 39 | 40 | if nargout > 2 41 | v = (lege.pols(x(:),k-1)).'; 42 | d = (2.0*(1:k) - 1)/2.0; 43 | u = ((v).*(w(:)*d)).'; 44 | end 45 | -------------------------------------------------------------------------------- /chunkie/+lege/intmat.m: -------------------------------------------------------------------------------- 1 | function [aint,u,v] = intmat(n,u,v) 2 | %INTMAT returns the spectral integration matrix on n Gaussian nodes 3 | % a transcription of part of the Rokhlin routine legeinmt 4 | % 5 | % input: 6 | % n - the number of Gaussian nodes 7 | % 8 | % optional inputs: 9 | % u - k x k matrix mapping values at legendre nodes to legendre series 10 | % coefficients 11 | % v - k x k matrix mapping legendre series coefficients to values at 12 | % legendre nodes 13 | % 14 | % output: 15 | % 16 | 17 | if nargin < 3 18 | [~,~,u,v] = lege.exps(n); 19 | end 20 | 21 | tmp = lege.intpol(u,'original'); 22 | aint = v*tmp(1:end-1,:); 23 | 24 | end 25 | -------------------------------------------------------------------------------- /chunkie/+lege/intpol.m: -------------------------------------------------------------------------------- 1 | function intcoeffs = intpol(coeffs,const_option) 2 | %LEGE.INTPOL compute the coefficients of the indefinite 3 | % integral of the polynomial with the coefficients given on 4 | % input 5 | % 6 | % input: 7 | % coeffs - array of Legendre series coefficients. if matrix, each column 8 | % contains the Legendres series coefficients of a separate function 9 | % 10 | % optional input: 11 | % const_option - string. default ('true'). If 'true', then the constant on 12 | % output is such that the polynomial(s) described by intcoeffs on output 13 | % take the value zero at -1. If 'original', then the constant on output 14 | % is such that the polynomial(s) described by intcoeffs(1:end-1,:) on 15 | % output take the value zero at -1. This is used for a spectral 16 | % integration matrix taking point values to point values on a grid 17 | % of the same order. 18 | % 19 | % output: 20 | % intcoeffs - array of Legendre series coefficients for a definte integral 21 | % of the input Legendre series 22 | % 23 | 24 | if nargin < 2 25 | const_option = 'true'; 26 | end 27 | 28 | sz = size(coeffs); 29 | szint = sz; szint(1) = szint(1)+1; 30 | intcoeffs = zeros(szint); 31 | 32 | if strcmpi(const_option,'true') 33 | ncc = szint(1); 34 | elseif strcmpi(const_option,'original') 35 | ncc = szint(1)-1; 36 | else 37 | error('LEGE.INTPOL: unknown option for constant'); 38 | end 39 | 40 | for i = 2:sz(1) 41 | j = i-1; 42 | intcoeffs(i+1,:) = coeffs(i,:)/(2*j+1); 43 | intcoeffs(i-1,:) = -coeffs(i,:)/(2*j+1)+intcoeffs(i-1,:); 44 | end 45 | 46 | intcoeffs(2,:) = coeffs(1,:)+intcoeffs(2,:); 47 | 48 | sss=-1; 49 | dd = zeros(size(intcoeffs(end,:))); 50 | for k = 2:ncc 51 | dd=dd+intcoeffs(k,:)*sss; 52 | sss=-sss; 53 | end 54 | intcoeffs(1,:)=-dd; 55 | 56 | end -------------------------------------------------------------------------------- /chunkie/+lege/matrin.m: -------------------------------------------------------------------------------- 1 | function [mat,x,w,u,v] = matrin(n,xs,varargin) 2 | %LEGE.MATRIN form the matrix for interpolating from n Legendre nodes to 3 | % the points xs 4 | % 5 | % optionally returns the roots, weights, and matrices for switching 6 | % between values and coefficients (u : values -> coeffs, 7 | % v : coeffs -> values), which is the output of LEGE.EXPS 8 | 9 | if nargin > 2 10 | u = varargin{1}; 11 | end 12 | 13 | if (nargin < 3 || nargout > 1) 14 | 15 | [x,w,u,v] = lege.exps(n); 16 | end 17 | 18 | xsvals = lege.pols(xs,n-1); 19 | 20 | mat = (xsvals).'*u; 21 | 22 | end -------------------------------------------------------------------------------- /chunkie/+lege/pol.m: -------------------------------------------------------------------------------- 1 | function [pol,der] = pol(xs,n) 2 | %POL evaluate nth order Legendre polynomial via recursion 3 | % 4 | % Copyright (C) 2009: Vladimir Rokhlin 5 | % 6 | % This software is being released under a modified FreeBSD license 7 | % 8 | 9 | % 10 | % if n=0 or n=1 - exit 11 | % 12 | 13 | if (n<=0) 14 | pol=ones(size(xs)); 15 | der=zeros(size(xs)); 16 | return 17 | end 18 | 19 | if (n==1) 20 | pol=xs; 21 | der=ones(size(xs)); 22 | return 23 | end 24 | 25 | pk = ones(size(xs)); 26 | pol = xs; 27 | 28 | % n is greater than 1. conduct recursion 29 | % 30 | 31 | for k=1:(n-1) 32 | pkm1=pk; 33 | pk=pol; 34 | pol= ( (2*k+1)*xs.*pk-k*pkm1 )/(k+1); 35 | end 36 | 37 | 38 | % calculate the derivative 39 | % 40 | 41 | der=n*(xs.*pol-pk)./(xs.^2-1); 42 | 43 | end 44 | -------------------------------------------------------------------------------- /chunkie/+lege/pols.m: -------------------------------------------------------------------------------- 1 | function [pols,ders] = pols(xs,n) 2 | %LEGE.POLS evaluate up to nth degree Legendre polynomial via recursion 3 | % 4 | % Syntax: 5 | % 6 | % [pols,ders] = lege.pols(xs,n); 7 | % 8 | % Input: 9 | % xs - points where you want to evaluate the Legendre polynomials 10 | % n - highest degree polynomial of interest 11 | % 12 | % Output: 13 | % pols - (n+1) x size(xs) array of polynomial values. pols(i,j) has the 14 | % value P_{i-1}(xs(j)) 15 | % ders - (n+1) x size(xs) array of polynomial derivative values. 16 | % ders(i,j) has the value P'_{i-1}(xs(j)) 17 | % 18 | % see also LEGE.POL 19 | 20 | % 21 | % Copyright (C) 2009: Vladimir Rokhlin 22 | % 23 | % This software is being released under a modified FreeBSD license 24 | % 25 | 26 | assert(n>=0,'n must be non-negative'); 27 | szx = size(xs); 28 | xs = xs(:); 29 | pols = zeros(length(xs),n+1); 30 | 31 | pols(:,1)=ones(length(xs),1); 32 | ders(:,1)=zeros(length(xs),1); 33 | 34 | if (n<=0) 35 | 36 | pols = reshape(pols.',[n+1, szx]); 37 | ders = reshape(ders.',[n+1, szx]); 38 | return 39 | end 40 | 41 | pols(:,2)=xs(:); 42 | ders(:,2)=ones(length(xs),1); 43 | 44 | if (n==1) 45 | 46 | pols = reshape(pols.',[n+1, szx]); 47 | ders = reshape(ders.',[n+1, szx]); 48 | return 49 | end 50 | 51 | pk = ones(length(xs),1); 52 | 53 | % n is greater than 1. conduct recursion 54 | % 55 | 56 | xs2m1 = xs.^2-1.0; 57 | pkp1 = pols(:,2); 58 | 59 | for k=1:(n-1) 60 | pkm1=pk; 61 | pk = pkp1; 62 | pkp1 = ( (2*k+1)*xs.*pk-k*pkm1 )/(k+1); 63 | pols(:,k+2) = pkp1; 64 | ders(:,k+2) = (k+1)*(xs.*pkp1-pk)./xs2m1; 65 | end 66 | 67 | pols = reshape(pols.',[n+1, szx]); 68 | ders = reshape(ders.',[n+1, szx]); 69 | 70 | end 71 | -------------------------------------------------------------------------------- /chunkie/+lege/polsum.m: -------------------------------------------------------------------------------- 1 | function [pol,der,tot] = polsum(xs,n) 2 | %POLSUM evaluate nth order Legendre polynomial via recursion along with the 3 | % sum of the squared values of P_k(xs) divided by k+1+0.5 (divided by 2 4 | % for P_0 and by 1.5 for P_1) --- useful for computing the roots 5 | % 6 | % Copyright (C) 2009: Vladimir Rokhlin 7 | % 8 | % This software is being released under a modified FreeBSD license 9 | % 10 | 11 | % 12 | % if n=0 or n=1 - exit 13 | % 14 | pol=ones(size(xs)); 15 | der=zeros(size(xs)); 16 | tot = pol.^2/2.0; 17 | 18 | if (n<=0) 19 | return 20 | end 21 | 22 | pol=xs; 23 | der=ones(size(xs)); 24 | tot=tot+pol.^2.*(1+0.5); 25 | 26 | if (n==1) 27 | return 28 | end 29 | 30 | pk = ones(size(xs)); 31 | pol = xs; 32 | 33 | % n is greater than 1. conduct recursion 34 | % 35 | 36 | for k=1:(n-1) 37 | pkm1=pk; 38 | pk=pol; 39 | pol= ( (2*k+1)*xs.*pk-k*pkm1 )/(k+1); 40 | tot=tot+pol.^2.*(k+1+0.5); 41 | end 42 | 43 | 44 | % calculate the derivative 45 | % 46 | 47 | der=n*(xs.*pol-pk)./(xs.^2-1); 48 | 49 | end 50 | -------------------------------------------------------------------------------- /chunkie/+lege/rts_stab.m: -------------------------------------------------------------------------------- 1 | function [ts,whts] = rts_stab(n) 2 | %LEGE.RTS_STAB computes the nodes and weights for Legendre polynomials 3 | % in O(n^2) time but is generally more stable than LEGE.RTS. 4 | % A transcription of the original Rokhlin routine 5 | % 6 | % Note: the original Fortran routine supports extended precision, 7 | % this routine does not 8 | % 9 | % Input parameters: 10 | % 11 | % n - the number of nodes to be returned 12 | % 13 | % Output parameters: 14 | % 15 | % ts - the n Gaussian nodes on the interval [-1,1] 16 | % whts - the n Gaussian weights on the interval [-1,1] 17 | % 18 | 19 | % Copyright (C) 2009: Vladimir Rokhlin 20 | % 21 | % This software is being released under a modified FreeBSD license 22 | % 23 | 24 | % 25 | % 26 | % . . . determine the number of Taylor coefficients 27 | % to be used 28 | % 29 | 30 | 31 | nnewt = 10; 32 | nstop = 3; 33 | stoptol = 1e-12; 34 | 35 | % 36 | % . . . construct the array of initial approximations 37 | % to the roots of the n-th legendre polynomial 38 | % 39 | 40 | ifodd = mod(n,2); 41 | % 42 | h=pi/(2*n); 43 | 44 | % work on right half of interval, starting guess is Chebyshev 45 | % 46 | rstart = (n-ifodd)/2+1; 47 | tsr = -cos((2*(rstart:n)-1)*h); 48 | tsr = tsr(:); 49 | 50 | % find roots with Newton 51 | 52 | % evaluate at first point O(n), remainder with updates 53 | 54 | 55 | for kk = 1:length(tsr) 56 | x1 = tsr(kk); 57 | 58 | % conduct newton 59 | 60 | ifstop=0; 61 | for i=1:nnewt 62 | 63 | [pol,der] = lege.pol(x1,n); 64 | x1=x1-pol/der; 65 | 66 | if(abs(pol) < stoptol); ifstop=ifstop+1; end 67 | if(ifstop >= nstop); break; end 68 | end 69 | 70 | tsr(kk)=x1; 71 | end 72 | 73 | ts = zeros(n,1); 74 | ts(rstart:n) = tsr(:); 75 | ts(1:(rstart+ifodd-1)) = -flipud(tsr); 76 | 77 | if nargout > 1 78 | [~,~,totr] = lege.polsum(tsr,n); 79 | whts = zeros(n,1); 80 | whts(rstart:n) = 1./totr(:); 81 | whts(1:(rstart+ifodd-1)) = flipud(1./totr(:)); 82 | end 83 | -------------------------------------------------------------------------------- /chunkie/+lege/tayl.m: -------------------------------------------------------------------------------- 1 | function [polnew,dernew] = tayl(pol,der,x,h,n,k) 2 | % 3 | % This subroutine evaluates the Taylor series for the 4 | % Legendre polynomial and its derivative at the point 5 | % x+h, starting with the value of the polynomial at the 6 | % point x, and the value of the derivative of that 7 | % polynomial. It uses the obvious three-term recursion 8 | % for the derivatives of Legendre polynomials. 9 | % c 10 | % Input parameters: 11 | % c 12 | % pol - the value of the polynomial at the pount x 13 | % der - the derivative of the polynomial at the pount x 14 | % x - the point where the values pol, der are specified 15 | % h - the polynomial and its derivative will be evaluated at 16 | % the point x+h 17 | % n - the order of the Legendre polynomial 18 | % k - the order of the Taylor series to be used 19 | % c 20 | % Output parameters: 21 | % c 22 | % polnew - the value of P_n at the point x+h 23 | % dernew - the value of the derivative of P_n at the point x+h 24 | % c 25 | % . . . evaluate the derivatives of P_n scaled by h^n/n!, 26 | % and polnew the taylor series for P_n and its 27 | % derivative 28 | % c 29 | 30 | q0 = pol; 31 | q1 = der.*h; 32 | q2 = (2*x.*der-n*(n+1)*pol)/(1-x.^2); 33 | q2 = q2.*h.^2/2.0; 34 | 35 | polnew=q0+q1+q2; 36 | dernew=q1./h+(q2*2)./h; 37 | 38 | if(k <= 2); return; end 39 | 40 | qi=q1; 41 | qip1=q2; 42 | 43 | for i = 1:k-2 44 | d=2*(x*(i+1).^2)./h.*qip1-(n*(n+1)-i*(i+1))*qi; 45 | d=(d/(i+1)/(i+2)).*h.^2./(1-x.^2); 46 | qip2=d; 47 | polnew=polnew+qip2; 48 | dernew=dernew+(d*(i+2))./h; 49 | qi=qip1; 50 | qip1=qip2; 51 | end 52 | 53 | end -------------------------------------------------------------------------------- /chunkie/@chunker/arclengthdens.m: -------------------------------------------------------------------------------- 1 | function ds = arclengthdens(chnkr) 2 | %ARCLENGTHDENS arc length density on chunks 3 | % 4 | % The smooth integration rule 5 | % on the ith chunk is 6 | % ds(:,i).*w 7 | % where w are the standard Legendre weights of appropriate order and 8 | % ds is the output of this routine 9 | % 10 | % Syntax: ds = arclengthdens(chnkr) 11 | % 12 | % Input: 13 | % chnkr - chunker object 14 | % 15 | % Output: 16 | % ds - arclength density 17 | % 18 | % Examples: 19 | % ds = arclengthdens(chnkr); 20 | % 21 | % see also WEIGHTS 22 | 23 | % author: Travis Askham (askhamwhat@gmail.com) 24 | 25 | ds = squeeze(sqrt(sum((chnkr.d).^2,1))); 26 | 27 | end 28 | -------------------------------------------------------------------------------- /chunkie/@chunker/arclengthfun.m: -------------------------------------------------------------------------------- 1 | function [s,nchs,chnkr] = arclengthfun(chnkr) 2 | %ARCLENGTHFUN 3 | % returns the values of s (arclength) along the 4 | % curve. if curve is multiple components, get 5 | % a different function per component 6 | % 7 | 8 | [~,~,info] = sortinfo(chnkr); 9 | chnkr = sort(chnkr); 10 | 11 | ncomp = info.ncomp; 12 | nchs = info.nchs; 13 | istart = 1; 14 | 15 | A = lege.intmat(chnkr.k); 16 | ds = arclengthdens(chnkr); 17 | chunklens = chunklen(chnkr); 18 | s = A*ds; 19 | 20 | for i = 1:ncomp 21 | nch = nchs(i); 22 | indsi = istart:(istart+nch-1); 23 | sstart = 0; 24 | for j = indsi 25 | lj = chunklens(j); 26 | s(:,j) = s(:,j)+sstart; 27 | sstart = sstart+lj; 28 | end 29 | istart = istart + nch; 30 | end 31 | -------------------------------------------------------------------------------- /chunkie/@chunker/area.m: -------------------------------------------------------------------------------- 1 | function a = area(chnkr) 2 | %AREA compute area of a closed, 2D chunker curve 3 | % 4 | % Syntax: a = area(chnkr) 5 | % 6 | % Input: 7 | % chnkr - chunker object. Must have chnkr.dim==2, all(chnkr.adj) ~= 0, 8 | % i.e. must be a closed 2d curve (or collection of closed curves) 9 | % 10 | % Output: 11 | % a - area 12 | % 13 | % Examples: 14 | % a = area(chnkr) 15 | % 16 | 17 | % author: Travis Askham (askhamwhat@gmail.com) 18 | 19 | assert(chnkr.dim == 2, ... 20 | 'area only well-defined for 2d chunkers'); 21 | assert(nnz(chnkr.adj == 0) == 0, ... 22 | 'area only well-defined for closed 2d chunkers'); 23 | assert(~any(chnkr.vertdeg > 2), ... 24 | 'area not well-defined for higher order vertices'); 25 | 26 | wts = chnkr.wts; 27 | rnorm = chnkr.n; 28 | igrand = sum(rnorm.*(chnkr.r),1); igrand = igrand(:); 29 | a = sum(wts(:).*igrand)/chnkr.dim; 30 | 31 | end 32 | -------------------------------------------------------------------------------- /chunkie/@chunker/centroids.m: -------------------------------------------------------------------------------- 1 | function ctrs = centroids(chnkr) 2 | %CENTROIDS 3 | % 4 | % Get the center of mass of each chunk 5 | 6 | k = chnkr.k; 7 | nch = chnkr.nch; 8 | dim = chnkr.dim; 9 | w = chnkr.wstor; 10 | ww = repmat( (w(:)).',dim,1); 11 | wall = reshape(ww(:)*ones(1,nch),dim,k,nch); 12 | 13 | ctrs = reshape(sum( (chnkr.r).*wall , 2),dim,nch)/2; 14 | 15 | end 16 | -------------------------------------------------------------------------------- /chunkie/@chunker/checkadjinfo.m: -------------------------------------------------------------------------------- 1 | function ier = checkadjinfo(chnkr) 2 | %CHECKADJINFO checks adjacency vector for errors. based on attempting 3 | % a sort. 4 | % 5 | % This is merely a wrapper for sortinfo. 6 | % 7 | % Syntax: ier = checkadjinfo(chnkr) 8 | % 9 | % Input: 10 | % chnkr - chunker object 11 | % 12 | % Output: 13 | % ier - error flag 14 | % ier = 1, bad adj info, different number of left and right ends 15 | % ier = 2, bad adj info, missed/doubled chunks found 16 | % 17 | % Examples: 18 | % ier = checkadjinfo(chnkr) 19 | % 20 | % see also SORT, SORTINFO 21 | 22 | % author: Travis Askham (askhamwhat@gmail.com) 23 | 24 | [~,~,info] = sortinfo(chnkr); 25 | ier = info.ier; -------------------------------------------------------------------------------- /chunkie/@chunker/chunkends.m: -------------------------------------------------------------------------------- 1 | function [rend,tauend] = chunkends(chnkr,ich) 2 | %CHUNKENDS evaluate the endpoints of chunks in chunker object 3 | % 4 | % Syntax: [rend,tauend] = ends(chnkr,ich) 5 | % 6 | % Input: 7 | % chnkr - chunker object 8 | % 9 | % Optional input: 10 | % ich - list of indices (if not specified, computes all ends) 11 | % 12 | % Output: 13 | % rend - (dim,2,:) array, positions of end points for requested chuns 14 | % tauend - (dim,2,:) array, unit tangent vectors at end points 15 | % 16 | % Examples: 17 | % rend = ends(chnkr); 18 | % ich = [1 3 9]; 19 | % [rend,tauend] = ends(chnkr,ich); 20 | % 21 | 22 | % author: Travis Askham (askhamwhat@gmail.com) 23 | 24 | [~,~,u] = lege.exps(chnkr.k); 25 | pm1 = lege.pols(-1,chnkr.k-1); pm1 = pm1.'; 26 | p1 = lege.pols(1,chnkr.k-1); p1 = p1.'; 27 | 28 | pends = [pm1; p1]; 29 | 30 | if nargin < 2 31 | nch1 = chnkr.nch; 32 | dim = chnkr.dim; 33 | ich = 1:nch1; 34 | else 35 | nch1 = numel(ich); 36 | end 37 | 38 | dim = chnkr.dim; 39 | rend = zeros(dim,2,nch1); 40 | tauend = zeros(dim,2,nch1); 41 | 42 | for i = 1:nch1 43 | ii = ich(i); 44 | ri = chnkr.r(:,:,ii); 45 | di = chnkr.d(:,:,ii); 46 | cri = u*(ri.'); 47 | cdi = u*(di.'); 48 | rendi = pends*cri; rendi = rendi.'; 49 | dendi = pends*cdi; dendi = dendi.'; 50 | 51 | dsendi = sqrt(sum(dendi.^2,1)); 52 | tauendi = bsxfun(@rdivide,dendi,dsendi); 53 | 54 | rend(:,:,i) = rendi; 55 | tauend(:,:,i) = tauendi; 56 | end 57 | 58 | -------------------------------------------------------------------------------- /chunkie/@chunker/chunklen.m: -------------------------------------------------------------------------------- 1 | function lens = chunklen(chnkr,ich) 2 | %CHUNKLEN lengths of chunks in chunker object 3 | % 4 | % Syntax: lens = chunklen(chnkr,ich,w) 5 | % 6 | % Input: 7 | % chnkr - chunker object 8 | % 9 | % Optional input: 10 | % ich - subset of chunks to get lengths of 11 | % 12 | % Output: 13 | % lens - length of chunks 14 | % 15 | % Examples: 16 | % lens = chunklen(chnkr); 17 | % ich = [1,3,9]; 18 | % lens = chunklen(chnkr,ich); 19 | % 20 | 21 | % author: Travis Askham (askhamwhat@gmail.com) 22 | 23 | if nargin < 2 24 | ich = 1:chnkr.nch; 25 | end 26 | 27 | wts = chnkr.wts(:,ich); 28 | lens = sum(wts,1); lens = lens(:); 29 | 30 | end 31 | -------------------------------------------------------------------------------- /chunkie/@chunker/diffmat.m: -------------------------------------------------------------------------------- 1 | function D = diffmat(chnkr, p, type) 2 | %DIFFMAT spectral differentiation matrix with respect to arc length along a 3 | % chunker object 4 | % 5 | % Syntax: chnkr = DIFFMAT(chnkr, p, type) 6 | % 7 | % Input: 8 | % chnkr - the chunker object 9 | % 10 | % Optional inputs: 11 | % p - differentiation order (1) 12 | % type - type of spectral differentiation ('square') 13 | % - 'square' maps from an n-point grid to an n-point grid on each 14 | % panel. 15 | % - 'rectangular' maps from an n-point grid to an (n-p)-point grid 16 | % on each panel. 17 | % 18 | % Output: 19 | % D - chnkr.npt x chnkr.npt sparse block-diagonal differentiation matrix 20 | % 21 | % Examples: 22 | % D = diffmat(chnkr); 23 | % D = diffmat(chnkr, 2); 24 | % D = diffmat(chnkr, 'rect'); 25 | % 26 | % See also INTMAT. 27 | 28 | if ( nargin < 2 ) 29 | p = 1; 30 | type = 'square'; 31 | end 32 | 33 | if ( nargin < 3 ) 34 | if ( isstring(p) || ischar(p) ) 35 | type = p; 36 | p = 1; 37 | else 38 | type = 'square'; 39 | end 40 | end 41 | 42 | if ( ~(isnumeric(p) && isscalar(p) && p>=0 && floor(p) == p) ) 43 | error('CHUNKER:DIFFMAT:order', ... 44 | 'Differentiation order must be a nonnegative integer.'); 45 | end 46 | 47 | n = chnkr.k; 48 | Dleg = lege.dermat(n); 49 | ds = reshape(vecnorm(chnkr.d), [n 1 chnkr.nch]); 50 | D = Dleg ./ ds; 51 | 52 | % Take p-th derivative 53 | for k = 1:chnkr.nch 54 | D(:,:,k) = D(:,:,k)^p; 55 | end 56 | 57 | if ( strcmpi(type, 'rect') ) 58 | [~, ~, CfV, ~] = lege.exps(n); 59 | [~, ~, ~, VfC] = lege.exps(n-p); 60 | P = VfC * CfV(1:n-p,:); 61 | D = pagemtimes(P, D); 62 | end 63 | 64 | % Output a sparse block-diagonal matrix 65 | D = num2cell(D, [1 2]); 66 | D = matlab.internal.math.blkdiag(D{:}); 67 | 68 | end 69 | -------------------------------------------------------------------------------- /chunkie/@chunker/ellipses.m: -------------------------------------------------------------------------------- 1 | function ells = ellipses(chnkr,rho,opts) 2 | 3 | nch = chnkr.nch; 4 | nth = max(2*nch,20); 5 | 6 | k = chnkr.k; 7 | nch = chnkr.nch; 8 | dim = chnkr.dim; 9 | 10 | assert(dim == 2,'ellipse images only well defined in 2d'); 11 | 12 | zell = lege.bernstein_ellipse(nth,rho); 13 | 14 | rcoef = exps(chnkr); 15 | zcoef = reshape(rcoef(1,:,:)+1i*rcoef(2,:,:),k,nch); 16 | 17 | km1=k-1; 18 | zpols = lege.pols(zell,km1); 19 | zpols = zpols.'; 20 | 21 | ells = zpols*zcoef; 22 | ells = reshape([real(ells(:).');imag(ells(:).')],2,nth,nch); 23 | -------------------------------------------------------------------------------- /chunkie/@chunker/exps.m: -------------------------------------------------------------------------------- 1 | function [rc,dc,d2c] = exps(chnkr) 2 | %EXPS compute Legendre coefficients for the position, derivative, 3 | % and second derivative of the chunker object on each chunk. 4 | % 5 | % Syntax: [rc,dc,d2c] = exps(chnkr) 6 | % 7 | % Input: 8 | % chnkr - chunker object 9 | % 10 | % Output: 11 | % rc - coefficients for position on each chunk 12 | % dc - coefficients for derivative of position on each chunk 13 | % d2c - coefficients for 2nd derivative of position on each chunk 14 | % 15 | % Examples: 16 | % [rc,dc,d2c] = exps(chnkr) 17 | % [~,dc] = exps(chnkr) 18 | % 19 | 20 | % author: Travis Askham (askhamwhat@gmail.com) 21 | 22 | k = chnkr.k; nch = chnkr.nch; dim = chnkr.dim; 23 | 24 | [~,~,u] = lege.exps(k); 25 | 26 | rc = ipermute(reshape(u*reshape(permute(chnkr.r,[2 1 3]),k,nch*dim), ... 27 | k,dim,nch),[2 1 3]); 28 | 29 | if nargout > 1 30 | dc = ipermute(reshape(u*reshape(permute(chnkr.d,[2 1 3]),k,nch*dim), ... 31 | k,dim,nch),[2 1 3]); 32 | end 33 | 34 | if nargout > 2 35 | d2c = ipermute(reshape(u*reshape(permute(chnkr.d2,[2 1 3]),k,nch*dim), ... 36 | k,dim,nch),[2 1 3]); 37 | end 38 | -------------------------------------------------------------------------------- /chunkie/@chunker/intmat.m: -------------------------------------------------------------------------------- 1 | function imat = intmat(chnkr) 2 | %INTMAT returns the matrix of integration in arc length along the 3 | % chunker object. The constant of integration is selected such that the 4 | % integral is zero at the left end of the first chunk of the chunker. 5 | % 6 | % see also ARCLENGTHFUN 7 | 8 | panel_int = reshape(lege.intmat(chnkr.k), [chnkr.k, chnkr.k, 1]); 9 | ds = reshape(vecnorm(chnkr.d), [1, chnkr.k, chnkr.nch]); 10 | panel_int = panel_int .* ds; 11 | [~, w, ~, ~] = lege.exps(chnkr.k); 12 | ds = reshape(w, [chnkr.k, 1]) .* reshape(ds, [chnkr.k, chnkr.nch]); 13 | % Set diagonal blocks 14 | panel_int = num2cell(panel_int, [1 2]); 15 | imat = blkdiag(panel_int{:}); 16 | % maybe not the fast way to do this, but find the panel ordering 17 | order_vec = zeros(chnkr.nch, 1); 18 | j = 1; 19 | for i = 1:chnkr.nch 20 | order_vec(i) = j; 21 | j = chnkr.adj(2, j); 22 | end 23 | % Set off diagonal matrix components 24 | for i = 2:chnkr.nch 25 | for j = 1:(i - 1) 26 | 27 | u = 1 + (order_vec(i) - 1)*chnkr.k; 28 | v = 1 + (order_vec(j) - 1)*chnkr.k; 29 | tmp = ones(chnkr.k, 1) * ds(1:chnkr.k, order_vec(j))'; 30 | imat(u:u + chnkr.k - 1, v:v + chnkr.k - 1) = tmp; 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /chunkie/@chunker/max.m: -------------------------------------------------------------------------------- 1 | function rmax = max(obj) 2 | %MAX maximum value of each coordinate over chunker nodes 3 | % 4 | % This is *not* the maximum extent of the curve 5 | % 6 | % Syntax: rmax = max(chnkr) 7 | % 8 | % Input: 9 | % chnkr - chunker object 10 | % 11 | % Output: 12 | % rmax - chnkr.dim length vector of maximum node value in each direction 13 | % 14 | % Examples: 15 | % rmax = max(chnkr); 16 | % 17 | 18 | % author: Travis Askham (askhamwhat@gmail.com) 19 | 20 | rmax = max(real(reshape(obj.r,obj.dim,obj.k*obj.nch)),[],2); -------------------------------------------------------------------------------- /chunkie/@chunker/min.m: -------------------------------------------------------------------------------- 1 | function rmin = min(obj) 2 | %MIN minimum value of each coordinate over chunker nodes 3 | % 4 | % This is *not* the minimum extent of the curve 5 | % 6 | % Syntax: rmin = min(chnkr) 7 | % 8 | % Input: 9 | % chnkr - chunker object 10 | % 11 | % Output: 12 | % rmin - chnkr.dim length vector of minimum node value in each direction 13 | % 14 | % Examples: 15 | % rmin = min(chnkr); 16 | % 17 | 18 | % author: Travis Askham (askhamwhat@gmail.com) 19 | 20 | rmin = min(real(reshape(obj.r,obj.dim,obj.k*obj.nch)),[],2); -------------------------------------------------------------------------------- /chunkie/@chunker/move.m: -------------------------------------------------------------------------------- 1 | function obj = move(obj,r0,r1,trotat,scale) 2 | %MOVE update the position of a chunker by translation, rotation, and 3 | % scaling. 4 | % 5 | % Syntax 6 | % chnkr = chnkr.move(r0,r1,trotat,scale) 7 | % 8 | % will shift the chunker geometry by -r0, rotate it by angle trotat, 9 | % scale the points by the factor scale, and shift back by +r1, i.e. the 10 | % coordinates will be changed by 11 | % 12 | % r <- s*M*(r-r0) + r1 13 | % 14 | % where M is the rotation matrix for trotat radians and s is the scale 15 | % 16 | % Input: 17 | % r0 - length 2 array, center of rotation. if empty, r0=[0;0] 18 | % r1 - length 2 array, new center. if empty, r1=[0;0] 19 | % trotat - float, angle of rotation in radians. if empty, trotat=0 20 | % scale - float, scaling factor. ifempty, scale = 1 21 | % 22 | % Output: 23 | % chnkr - chunker object with positions, derivatives, normals etc updated 24 | % according to the formula above. 25 | % 26 | 27 | if nargin < 2 || isempty(r0) 28 | r0 = [0;0]; 29 | end 30 | if nargin < 3 || isempty(r1) 31 | r1 = [0;0]; 32 | end 33 | if nargin < 4 || isempty(trotat) 34 | trotat = 0; 35 | end 36 | if nargin < 5 || isempty(scale) 37 | scale = 1; 38 | end 39 | 40 | 41 | rsize = size(obj.r); 42 | 43 | rotmat = [cos(trotat),-sin(trotat);sin(trotat),cos(trotat)]; 44 | 45 | rnew = scale*rotmat*(obj.r(:,:)-r0) + r1; 46 | obj.r = reshape(rnew,rsize); 47 | 48 | dnew = scale*rotmat*(obj.d(:,:)); 49 | obj.d = reshape(dnew,rsize); 50 | 51 | d2new = scale*rotmat*(obj.d2(:,:)); 52 | obj.d2 = reshape(d2new,rsize); 53 | 54 | nnew = rotmat*(obj.n(:,:)); 55 | obj.n = reshape(nnew,rsize); 56 | 57 | obj.wts = weights(obj); 58 | 59 | end 60 | -------------------------------------------------------------------------------- /chunkie/@chunker/mtimes.m: -------------------------------------------------------------------------------- 1 | function chnkr = mtimes(A,chnkr) 2 | % * Matrix multiplication for chunker. Transforms curve positions by 3 | % r -> A*r and updates derivatives and normals accordingly. Note that this 4 | % routine can change the orientation if det(A) is not positive. 5 | % 6 | 7 | if isa(A,"numeric") && isa(chnkr,"chunker") 8 | dim = size(chnkr.r,1); 9 | if isscalar(A) 10 | A = A*eye(dim); 11 | end 12 | [m,n] = size(A); 13 | if n == dim && m == dim 14 | chnkr.r(:,:) = A*chnkr.r(:,:); 15 | chnkr.d(:,:) = A*chnkr.d(:,:); 16 | chnkr.d2(:,:) = A*chnkr.d2(:,:); 17 | chnkr.n = normals(chnkr); 18 | chnkr.wts = weights(chnkr); 19 | else 20 | error("CHUNKER:mtimes:invalid",... 21 | "matrix must have compatible size for transforming coordinates"); 22 | end 23 | elseif isnumeric(chnkr) && isscalar(chnkr) 24 | chnkr = mtimes(chnkr,A); 25 | elseif isnumeric(chnkr) 26 | error("CHUNKER:mtimes:invalid",... 27 | "product of chunker and matrix only defined for matrix on left"); 28 | else 29 | error("CHUNKER:mtimes:invalid",... 30 | "type not supported for product with chunker"); 31 | end -------------------------------------------------------------------------------- /chunkie/@chunker/normals.m: -------------------------------------------------------------------------------- 1 | function rnorms = normals(chnkr) 2 | %NORMALS compute normal vectors along boundary of 2D curve 3 | % 4 | % Syntax: rnorms = normals(chnkr) 5 | % 6 | % Input: 7 | % chnkr - chunker object 8 | % 9 | % Output: 10 | % rnorms - normals along boundary of chunker curve 11 | % 12 | % Examples: 13 | % rnorms = normals(chnkr) 14 | % 15 | 16 | % author: Travis Askham (askhamwhat@gmail.com) 17 | 18 | assert(chnkr.dim == 2,'normals only implemented for dim=2'); 19 | k = chnkr.k; 20 | nch = chnkr.nch; 21 | 22 | dd = sqrt(chnkr.dstor(1,:,1:nch).^2 + chnkr.dstor(2,:,1:nch).^2); 23 | rnorms = zeros(2,k,nch); 24 | rnorms(1,:,:) = chnkr.dstor(2,:,1:nch)./dd; 25 | rnorms(2,:,:) = -chnkr.dstor(1,:,1:nch)./dd; 26 | 27 | end 28 | 29 | -------------------------------------------------------------------------------- /chunkie/@chunker/normonesmat.m: -------------------------------------------------------------------------------- 1 | function mat = normonesmat(chnkr) 2 | %NORMONESMAT for 2D curves. Forms the matrix for the operator 3 | % 4 | % W[\mu](x) = n(x) \int n(y)\cdot \mu(y) \, dl 5 | % 6 | % which project a vector density (\mu) on the chunker onto the normal 7 | % vector along the chunker. This is a common operator in mechanics for 8 | % removing nullspaces 9 | % 10 | % Syntax: mat = normonesmat(chnkr) 11 | % 12 | % Input: 13 | % chnkr - chunker object 14 | % 15 | % Output: 16 | % mat - the matrix discretization of the operator W above. mat is 17 | % (2*chnkr.npt) x (2*chnkr.npt) 18 | % 19 | % Examples: 20 | % mat = normonesmat(chnkr) 21 | % 22 | % see also ONESMAT 23 | 24 | % author: Travis Askham (askhamwhat@gmail.com) 25 | 26 | wts = chnkr.wts; 27 | rnorms = chnkr.n; 28 | wts = wts(:); 29 | wts2 = repmat(wts.',2,1); 30 | wts2 = wts2(:).*rnorms(:); 31 | 32 | mat = bsxfun(@times,rnorms(:),wts2.'); 33 | 34 | end 35 | -------------------------------------------------------------------------------- /chunkie/@chunker/onesmat.m: -------------------------------------------------------------------------------- 1 | function mat = onesmat(chnkr) 2 | %ONESMAT Forms the matrix for the operator 3 | % 4 | % W[\mu](x) = \int \mu(y) dl 5 | % 6 | % which projects a scalar density (\mu) on the chunker onto the constant 7 | % vector along the chunker. This is a common operator for removing 8 | % nullspaces 9 | % 10 | % Syntax: mat = onesmat(chnkr) 11 | % 12 | % Input: 13 | % chnkr - chunker object 14 | % 15 | % Output: 16 | % mat - the matrix discretization of the operator W above. mat is 17 | % (chnkr.npt) x (chnkr.npt) 18 | % 19 | % Examples: 20 | % mat = onesmat(chnkr) 21 | % 22 | % see also NORMONESMAT 23 | 24 | % author: Travis Askham (askhamwhat@gmail.com) 25 | 26 | wts = chnkr.wts; 27 | wts = wts(:); 28 | temp = ones(size(wts)); 29 | mat = bsxfun(@times,temp,wts.'); 30 | 31 | end 32 | -------------------------------------------------------------------------------- /chunkie/@chunker/plot.m: -------------------------------------------------------------------------------- 1 | function plot(obj,varargin) 2 | %PLOT plot the xy-coordinates of the points of the chunker object 3 | % Must be a 2D chunker. Uses standard plotting commands 4 | % 5 | % Syntax: plot(chnkr,varargin) 6 | % 7 | % Input: 8 | % chnkr - chunker object 9 | % varargin - any of the standard plot commands 10 | % 11 | % Output: 12 | % none 13 | % 14 | % Examples: 15 | % plot(chnkr,'rx') % plots chunker with red x's for points 16 | % plot(chnkr,'b-','LineWidth',2) % plots chunker with thick blue lines 17 | % 18 | % see also PLOT3, QUIVER 19 | 20 | % author: Travis Askham (askhamwhat@gmail.com) 21 | 22 | ifhold = ishold(); 23 | 24 | for i = 1:length(obj) 25 | tmp = obj(i); 26 | assert(tmp.dim == 2,'for plot must be 2D chunker'); 27 | [tmp,info] = sort(tmp); 28 | ifclosed = info.ifclosed; 29 | nchs = info.nchs; 30 | istart = 1; 31 | for ii = 1:length(nchs) 32 | iend = istart+nchs(ii)-1; 33 | xs = tmp.r(1,:,istart:iend); xs = xs(:); 34 | ys = tmp.r(2,:,istart:iend); ys = ys(:); 35 | 36 | if ifclosed 37 | xs = [xs(:); xs(1)]; 38 | ys = [ys(:); ys(1)]; 39 | end 40 | 41 | if isreal(xs) 42 | plot(xs,ys,varargin{:}) 43 | else 44 | plot(real(xs),ys,varargin{:}) 45 | hold on; 46 | plot(real(xs),imag(xs),'b-') 47 | end 48 | hold on 49 | istart = istart+nchs(ii); 50 | end 51 | 52 | end 53 | 54 | hold off 55 | 56 | if ifhold 57 | hold on 58 | end -------------------------------------------------------------------------------- /chunkie/@chunker/plot3.m: -------------------------------------------------------------------------------- 1 | function plot3(obj,idata,varargin) 2 | %PLOT3 plot values in the specified data row as the z-coordinate with 3 | % the xy-coordinates the nodes of the chunker object. Must be a 2D chunker. 4 | % Uses standard plotting commands 5 | % 6 | % Syntax: plot3(chnkr,idata,varargin) 7 | % 8 | % Input: 9 | % chnkr - chunker object 10 | % idata - chunker data row to plot 11 | % varargin - any of the standard plot commands 12 | % 13 | % Output: 14 | % none 15 | % 16 | % Examples: 17 | % % add a data row and plot it 18 | % chnkr = chnkr.makedatarows(1); 19 | % fun1 = sin(chnkr.r(1,:)); 20 | % chnkr.data(1,:) = fun1; 21 | % plot3(chnkr,1,'rx') % plots curve with red x's for points 22 | % plot3(chnkr,1,'b-','LineWidth',2) % plots curve with thick blue lines 23 | % 24 | % see also PLOT, QUIVER 25 | 26 | % author: Travis Askham (askhamwhat@gmail.com) 27 | 28 | ifhold = ishold(); 29 | if nargin < 2 30 | idata = 1; 31 | end 32 | 33 | for i = 1:length(obj) 34 | tmp = obj(i); 35 | assert(tmp.hasdata); 36 | assert(tmp.dim == 2,'for plot must be 2D chunker'); 37 | [tmp,info] = sort(tmp); 38 | ifclosed = info.ifclosed; 39 | nchs = info.nchs; 40 | istart = 1; 41 | for ii = 1:length(nchs) 42 | iend = istart+nchs(ii)-1; 43 | xs = tmp.r(1,:,istart:iend); xs = xs(:); 44 | ys = tmp.r(2,:,istart:iend); ys = ys(:); 45 | zs = tmp.data(idata,:,istart:iend); zs = zs(:); 46 | 47 | if ifclosed 48 | xs = [xs(:); xs(1)]; 49 | ys = [ys(:); ys(1)]; 50 | zs = [zs(:); zs(1)]; 51 | end 52 | 53 | plot3(xs,ys,zs,varargin{:}) 54 | hold on 55 | istart = istart+nchs(ii); 56 | end 57 | 58 | end 59 | 60 | hold off 61 | 62 | if ifhold 63 | hold on 64 | end -------------------------------------------------------------------------------- /chunkie/@chunker/plus.m: -------------------------------------------------------------------------------- 1 | function g = plus(f,g) 2 | % + pointwise addition for chunker class 3 | % 4 | % Currently only supported for adding a constant vector to the chunker, 5 | % translating the curve 6 | 7 | if ~isa(g,"chunker") 8 | g = plus(g,f); 9 | elseif isa(f,'numeric') && numel(f) == size(g.r,1) 10 | assert(numel(f) == size(g.r,1),'CHUNKER:plus sizes incompatible'); 11 | g.r(:,:) = g.r(:,:) + f(:); 12 | else 13 | error('CHUNKER:plus:invalid', ... 14 | 'plus only supported for a vector of appropriate size and a chunker object'); 15 | end -------------------------------------------------------------------------------- /chunkie/@chunker/quiver.m: -------------------------------------------------------------------------------- 1 | function quiver(obj,varargin) 2 | %QUIVER quiver plot of chunker normal vectors in 2 dimensions 3 | % Uses standard quiver commands 4 | % 5 | % Syntax: quiver(chnkr,varargin) 6 | % 7 | % Input: 8 | % chnkr - chunker object 9 | % varargin - any of the standard quiver commands 10 | % 11 | % Output: 12 | % none 13 | % 14 | % Examples: 15 | % quiver(chnkr,'r','LineWidth',2) % quiver plot of chunker normals 16 | % % with thick red arrows 17 | % 18 | % see also PLOT, PLOT3 19 | 20 | % author: Travis Askham (askhamwhat@gmail.com) 21 | 22 | ifhold = ishold(); 23 | 24 | for i = 1:length(obj) 25 | tmp = obj(i); 26 | assert(tmp.dim == 2,'for quiver plot must be 2D chunker'); 27 | 28 | tmp = sort(tmp); 29 | xs = tmp.r(1,:,:); xs = xs(:); 30 | ys = tmp.r(2,:,:); ys = ys(:); 31 | 32 | rnorms = normals(tmp); 33 | 34 | u = rnorms(1,:,:); u = u(:); 35 | v = rnorms(2,:,:); v = v(:); 36 | 37 | quiver(xs,ys,u,v,varargin{:}); 38 | hold on 39 | 40 | end 41 | 42 | hold off 43 | 44 | if ifhold 45 | hold on 46 | end 47 | -------------------------------------------------------------------------------- /chunkie/@chunker/reflect.m: -------------------------------------------------------------------------------- 1 | function chnkr = reflect(chnkr,theta,r0,r1) 2 | %REFLECT reflect chunker object across line specified by angle 3 | % 4 | % Syntax 5 | % chnkr = chnkr.reflect(theta,r0,r1); 6 | % 7 | % will shift the chunker geometry by -r0, reflect it across the line 8 | % spanned by [cos(theta); sin(theta)] and shift back by +r1, i.e. the 9 | % coordinates will be changed by 10 | % 11 | % r <- M*(r-r0) + r1 12 | % 13 | % where M is the reflection matrix [cos(2*theta) sin(2*theta); sin(2*theta) 14 | % -cos(2*theta)] 15 | % 16 | % Input: 17 | % theta - float, angle made by reflection axis in radians. if empty, 18 | % theta=0 19 | % r0 - length 2 array, center of reflection if empty, r0=[0;0] 20 | % r1 - length 2 array, new center. if empty, r1=[0;0] 21 | % 22 | % Output: 23 | % chnkr - chunker object with positions, derivatives, normals etc updated 24 | % according to the formula above. 25 | % 26 | 27 | if nargin < 3 || isempty(r0) 28 | r0 = [0;0]; 29 | end 30 | if nargin < 4 || isempty(r1) 31 | r1 = [0;0]; 32 | end 33 | 34 | assert(isreal(theta),"reflect only supports real angles"); 35 | 36 | c = cos(2*theta); 37 | s = sin(2*theta); 38 | refmat = [c s; s -c]; 39 | 40 | chnkr.r(:,:) = refmat*(chnkr.r(:,:)-r0) + r1; 41 | chnkr.d(:,:) = refmat*chnkr.d(:,:); 42 | chnkr.d2(:,:) = refmat*chnkr.d2(:,:); 43 | chnkr.n(:,:) = refmat*chnkr.n(:,:); 44 | -------------------------------------------------------------------------------- /chunkie/@chunker/reverse.m: -------------------------------------------------------------------------------- 1 | function obj = reverse(obj) 2 | %REVERSE reverses the orientation of the chunker object 3 | % 4 | % Syntax: chnkr = reverse(chnkr) 5 | % 6 | % Input: 7 | % chnkr - chunker object 8 | % 9 | % Output: 10 | % chnkr - modified chunker object 11 | % 12 | % Examples: 13 | % chnkr = reverse(chnkr) 14 | % 15 | % see also SORT 16 | 17 | % author: Travis Askham (askhamwhat@gmail.com) 18 | 19 | k = obj.k; 20 | obj.r = obj.r(:,k:-1:1,:); 21 | obj.d = -obj.d(:,k:-1:1,:); 22 | obj.d2 = obj.d2(:,k:-1:1,:); 23 | obj.adj = obj.adj([2 1],:); 24 | obj.n = -obj.n(:,k:-1:1,:); 25 | obj.wts = obj.wts(k:-1:1,:); 26 | 27 | 28 | end -------------------------------------------------------------------------------- /chunkie/@chunker/rotate.m: -------------------------------------------------------------------------------- 1 | function chnkr = rotate(chnkr,theta,r0,r1) 2 | %ROTATE rotate chunker object by specified angle 3 | % 4 | % Syntax 5 | % chnkr = chnkr.rotate(theta,r0,r1); 6 | % 7 | % will shift the chunker geometry by -r0, rotate it by angle trotat, 8 | % and shift back by +r1, i.e. the coordinates will be changed by 9 | % 10 | % r <- M*(r-r0) + r1 11 | % 12 | % where M is the rotation matrix for theta radians 13 | % 14 | % Input: 15 | % theta - float, angle of rotation in radians. if empty, trotat=0 16 | % r0 - length 2 array, center of rotation. if empty, r0=[0;0] 17 | % r1 - length 2 array, new center. if empty, r1=[0;0] 18 | % 19 | % Output: 20 | % chnkr - chunker object with positions, derivatives, normals etc updated 21 | % according to the formula above. 22 | % 23 | 24 | if nargin < 3 || isempty(r0) 25 | r0 = [0;0]; 26 | end 27 | if nargin < 4 || isempty(r1) 28 | r1 = [0;0]; 29 | end 30 | 31 | assert(isreal(theta),"rotate only supports real angles"); 32 | 33 | c = cos(theta); 34 | s = sin(theta); 35 | rotmat = [c -s; s c]; 36 | 37 | chnkr.r(:,:) = rotmat*(chnkr.r(:,:)-r0) + r1; 38 | chnkr.d(:,:) = rotmat*chnkr.d(:,:); 39 | chnkr.d2(:,:) = rotmat*chnkr.d2(:,:); 40 | chnkr.n(:,:) = rotmat*chnkr.n(:,:); 41 | -------------------------------------------------------------------------------- /chunkie/@chunker/scatter.m: -------------------------------------------------------------------------------- 1 | function scatter(obj,varargin) 2 | %SCATTER scatter plot of the coordinates of the chunker object. 3 | % Must be a 2D chunker. Faster than plot --> no sorting required 4 | % Uses standard scatter commands 5 | % 6 | % Syntax: scatter(chnkr,varargin) 7 | % 8 | % Input: 9 | % chnkr - chunker object 10 | % varargin - any of the scatter commands 11 | % 12 | % Output: 13 | % none 14 | % 15 | % Examples: 16 | % scatter(chnkr,'ro') % scatter plot of chunker points as red circles 17 | % 18 | % see also PLOT 19 | 20 | % author: Travis Askham (askhamwhat@gmail.com) 21 | 22 | assert(obj.dim == 2,'for scatter plot must be 2D chunker'); 23 | xs = obj.r(1,:,:); xs = xs(:); 24 | ys = obj.r(2,:,:); ys = ys(:); 25 | 26 | scatter(xs,ys,varargin{:}); -------------------------------------------------------------------------------- /chunkie/@chunker/signed_curvature.m: -------------------------------------------------------------------------------- 1 | function kappa = signed_curvature(chnkr) 2 | %CURVATURE returns the signed curvature at each node 3 | % 4 | % (x'y'' - y'x'')/(x'^2+y'^2)^(3/2) 5 | % 6 | 7 | assert(size(chnkr.r,1) == 2,'signed curvature only defined in 2D'); 8 | kappa = (chnkr.d(1,:).*chnkr.d2(2,:)- ... 9 | chnkr.d(2,:).*chnkr.d2(1,:))./(sqrt(sum(chnkr.d(:,:).^2,1)).^3); 10 | kappa = reshape(kappa,chnkr.k,chnkr.nch); 11 | end -------------------------------------------------------------------------------- /chunkie/@chunker/sort.m: -------------------------------------------------------------------------------- 1 | function [chnkr,info] = sort(chnkr) 2 | %SORT sort the chunker object so that adjacent chunks have sequential 3 | % indices 4 | % 5 | % Syntax: [chnkr,info] = sort(chnkr) 6 | % 7 | % Input: 8 | % chnkr - chunker object 9 | % 10 | % Output: 11 | % chnkr - the sorted chunker 12 | % info - adjacency info structure 13 | % info.ncomp - number of curve components detected 14 | % info.nchs - number of chunks on each component 15 | % info.ifclosed - whether/or not each detected component is closed 16 | % info.ier - error flag 17 | % ier = 1, bad adj info, different number of left and right ends 18 | % ier = 2, bad adj info, missed/doubled chunks found 19 | % 20 | % Examples: 21 | % chnkr = sort(chnkr) 22 | % [chnkr,info] = sort(chnkr) 23 | % 24 | % see also SORTINFO 25 | 26 | % author: Travis Askham (askhamwhat@gmail.com) 27 | 28 | [inds,adjs,info] = sortinfo(chnkr); 29 | 30 | % reorder 31 | 32 | chnkr.r = chnkr.r(:,:,inds); 33 | chnkr.d = chnkr.d(:,:,inds); 34 | chnkr.d2 = chnkr.d2(:,:,inds); 35 | chnkr.n = chnkr.n(:,:,inds); 36 | chnkr.wts = chnkr.wts(:,inds); 37 | 38 | indinv = 1:length(inds); 39 | indinv(inds) = 1:length(inds); 40 | 41 | for i = 1:chnkr.nvert 42 | ivert = chnkr.vert{i}; 43 | chnkr.vert{i} = indinv(ivert); 44 | end 45 | 46 | if chnkr.hasdata 47 | chnkr.data = chnkr.data(:,:,inds); 48 | end 49 | 50 | chnkr.adj = adjs; 51 | 52 | 53 | end 54 | -------------------------------------------------------------------------------- /chunkie/@chunker/tangents.m: -------------------------------------------------------------------------------- 1 | function ts = tangents(chnkr) 2 | %TANGENTS return unit tangent vectors along chunker curve 3 | % 4 | % Syntax: ts = tangents(chnkr) 5 | % 6 | % Input: 7 | % chnkr - chunker object 8 | % 9 | % Output: 10 | % ts - unit tangent vector along curve 11 | % 12 | % Examples: 13 | % ts = tangents(chnkr); 14 | % 15 | 16 | % author: Travis Askham (askhamwhat@gmail.com) 17 | 18 | d = chnkr.d; 19 | 20 | dd = sqrt(sum(abs(d).^2,1)); 21 | ts = bsxfun(@rdivide,chnkr.d,dd); 22 | 23 | end 24 | 25 | -------------------------------------------------------------------------------- /chunkie/@chunker/taus.m: -------------------------------------------------------------------------------- 1 | function tau = taus(chnkr) 2 | %TAUS return unit tangent vectors along chunker curve 3 | % 4 | % Syntax: tau = taus(chnkr) 5 | % 6 | % Input: 7 | % chnkr - chunker object 8 | % 9 | % Output: 10 | % tau - unit tangent vector along curve 11 | % 12 | % Examples: 13 | % tau = taus(chnkr); 14 | % 15 | 16 | % author: Travis Askham (askhamwhat@gmail.com) 17 | 18 | warning('taus is deprecated and will be removed. use tangents instead'); 19 | 20 | k = chnkr.k; 21 | nch = chnkr.nch; 22 | d = chnkr.d; 23 | 24 | dd = sqrt(sum(abs(d).^2,1)); 25 | tau = bsxfun(@rdivide,chnkr.d,dd); 26 | 27 | end 28 | 29 | -------------------------------------------------------------------------------- /chunkie/@chunker/upsample.m: -------------------------------------------------------------------------------- 1 | function [chnkrup,sigmaup] = upsample(chnkr,kup,sigma) 2 | %UPSAMPLE return a chunker object which has been upsampled to a finer grid 3 | % 4 | % [chnkrup,sigmaup] = upsample(chnkr,kup,sigma); 5 | % 6 | % input: 7 | % chnkr - chunker object 8 | % kup - integer, order of panels for upsampled chunker 9 | % sigma - optional, function on chunker to upsample 10 | % 11 | % output: 12 | % 13 | % chnkrup - upsampled verson of chunker object 14 | % sigmaup - upsampled function (if sigma provided), empty otherwise 15 | % 16 | 17 | k = chnkr.k; 18 | dim = chnkr.dim; 19 | nch = chnkr.nch; 20 | 21 | [~,~,u] = lege.exps(k); 22 | [tu,wu,~,vu] = lege.exps(kup); 23 | 24 | upmat = vu(:,1:k)*u; 25 | 26 | pref = []; pref.k = kup; 27 | chnkrup = chunker(pref,tu,wu); 28 | chnkrup = chnkrup.addchunk(nch); 29 | 30 | nn = dim*nch; 31 | 32 | chnkrup.r = permute(reshape(upmat*reshape( ... 33 | permute(chnkr.r,[2,1,3]),k,nn),kup,dim,nch),[2,1,3]); 34 | chnkrup.d= permute(reshape(upmat*reshape( ... 35 | permute(chnkr.d,[2,1,3]),k,nn),kup,dim,nch),[2,1,3]); 36 | chnkrup.d2= permute(reshape(upmat*reshape( ... 37 | permute(chnkr.d2,[2,1,3]),k,nn),kup,dim,nch),[2,1,3]); 38 | chnkrup.adj= chnkr.adj; 39 | 40 | chnkrup.n = normals(chnkrup); 41 | chnkrup.wts = weights(chnkrup); 42 | 43 | if chnkr.hasdata 44 | ndata = size(chnkr.data,1); 45 | nndata = ndata*nch; 46 | chnkrup = chnkrup.makedatarows(ndata); 47 | chnkrup.data = permute(reshape(upmat*reshape( ... 48 | permute(chnkr.data,[2,1,3]),k,nndata),kup,ndata,nch),[2,1,3]); 49 | end 50 | 51 | if nargin > 2 52 | dimsig = numel(sigma)/(nch*k); 53 | sigma= reshape(sigma,dimsig,k,nch); 54 | nnsig = dimsig*nch; 55 | sigmaup = permute(reshape(upmat*reshape( ... 56 | permute(sigma,[2,1,3]),k,nnsig),kup,dimsig,nch),[2,1,3]); 57 | else 58 | sigmaup = []; 59 | end 60 | -------------------------------------------------------------------------------- /chunkie/@chunker/weights.m: -------------------------------------------------------------------------------- 1 | function wts = weights(chnkr) 2 | %WEIGHTS compute integration weights suitable for smooth functions defined 3 | % on the chunker object. This routine is intended for use by chunker object 4 | % constructors. It is not intended to be called by users, because 5 | % such weights should already be stored in the chunker object. 6 | % 7 | % This is the standard Legendre weights scaled to the chunks 8 | % 9 | % Syntax: wts = weights(chnkr) 10 | % 11 | % Input: 12 | % chnkr - chunker object 13 | % 14 | % Output: 15 | % wts - smooth integration weights 16 | % 17 | % Examples: 18 | % wts = weights(chnkr) 19 | % 20 | 21 | % author: Travis Askham (askhamwhat@gmail.com) 22 | 23 | k = chnkr.k; 24 | nch = chnkr.nch; 25 | w = chnkr.wstor; 26 | wts = reshape(sqrt(sum((chnkr.d).^2,1)),k,nch); 27 | wts = wts.*w(:); 28 | 29 | end 30 | -------------------------------------------------------------------------------- /chunkie/@chunker/whts.m: -------------------------------------------------------------------------------- 1 | function wts = whts(chnkr) 2 | 3 | 4 | warning('whts is deprecated and will be removed, use weights instead'); 5 | 6 | wts = weights(chnkr); 7 | 8 | end 9 | -------------------------------------------------------------------------------- /chunkie/@chunkerpref/chunkerpref.m: -------------------------------------------------------------------------------- 1 | classdef chunkerpref 2 | %CHUNKERPREF class for storing preferences for chunker objects and 3 | % sets defaults 4 | 5 | properties 6 | nchmax 7 | k 8 | dim 9 | nchstor 10 | verttol 11 | end 12 | 13 | methods 14 | function obj = chunkerpref(pref) 15 | %CHUNKERPREF construct chunkerpref from either a given 16 | % chunkerpref or struct listing properties to set 17 | 18 | assert(nargin <= 1,'number of arguments must be 0 or 1'); 19 | defpref = chunkerpref.defaultprefs(); 20 | if nargin < 1 || isempty(pref) 21 | pref = defpref; 22 | end 23 | assert(or(isstruct(pref),isa(pref,'chunkerpref')), ... 24 | 'bad input, must be empty, a struct, or a chunkerpref object'); 25 | if isa(pref,'chunkerpref') 26 | % do nothing if input is a chunkerpref 27 | obj = pref; 28 | else 29 | deffields = fieldnames(defpref); 30 | fields = fieldnames(pref); 31 | 32 | % assign defaults first, then overwrite 33 | for i = 1:length(deffields) 34 | obj.(deffields{i}) = defpref.(deffields{i}); 35 | end 36 | for i = 1:length(fields) 37 | obj.(fields{i}) = pref.(fields{i}); 38 | end 39 | end 40 | end 41 | end 42 | methods (Static) 43 | function defpref = defaultprefs() 44 | defpref = []; 45 | defpref.nchmax = 10000; 46 | defpref.k = 16; 47 | defpref.dim = 2; 48 | defpref.nchstor = 4; 49 | defpref.verttol = 1e-12; 50 | end 51 | end 52 | end -------------------------------------------------------------------------------- /chunkie/@chunkgraph/build_v2emat.m: -------------------------------------------------------------------------------- 1 | function A = build_v2emat(obj) 2 | %V2EMAT get a "vertex to edge" matrix for the chunkgraph object 3 | % 4 | % input: obj - a chunkgraph object 5 | % 6 | % output: A - a nedges x nverts sparse matrix 7 | % A(i,j) = 1 if edge i starts at vertex j 8 | % A(i,j) = -1 if edge i ends at vertex j 9 | % A(i,j) = 2 if edge i starts and ends at vertex j 10 | % 11 | 12 | nverts = size(obj.verts,2); 13 | nedges = size(obj.edgesendverts,2); 14 | 15 | 16 | ii = zeros(2*nedges,1); 17 | jj = zeros(2*nedges,1); 18 | vv = zeros(2*nedges,1); 19 | nf = 0; 20 | 21 | for i = 1:nedges 22 | j1 = obj.edgesendverts(1,i); 23 | j2 = obj.edgesendverts(2,i); 24 | if ~isnan(j1) && ~isnan(j2) 25 | if j1 == j2 26 | nf = nf + 1; 27 | ii(nf) = i; 28 | jj(nf) = j1; 29 | vv(nf) = 2; 30 | else 31 | nf = nf + 1; 32 | ii(nf) = i; 33 | jj(nf) = j1; 34 | vv(nf) = -1; 35 | nf = nf + 1; 36 | ii(nf) = i; 37 | jj(nf) = j2; 38 | vv(nf) = 1; 39 | end 40 | end 41 | end 42 | 43 | A = sparse(ii(1:nf),jj(1:nf),vv(1:nf),nedges,nverts); 44 | 45 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/find_edge_regions.m: -------------------------------------------------------------------------------- 1 | function edge_regs = find_edge_regions(obj) 2 | %FIND_EDGE_REGIONS find regions on either side of the edges 3 | % in a chunkgraph. 4 | % 5 | % Syntax: edge_regs = find_edge_regions(obj) 6 | % 7 | % Input: 8 | % obj - chunkgraph object describing curve 9 | % 10 | % Output: 11 | % edge_regs - (2,nedge) array where nedges 12 | % is the number of edges in the chunkgraph. 13 | % edge_reg(1,i) is index of the region in which the 14 | % normal to edge i is pointing and edge_reg(2,i) 15 | % is the index corresponding to the negative of 16 | % the normal. 17 | % 18 | % author: Tristan Goodwill 19 | 20 | 21 | edge_regs = zeros(2,size(obj.edgesendverts,2)); 22 | nreg = length(obj.regions); 23 | for i = 1:nreg 24 | id_edge = obj.regions{i}{1}; 25 | edge_regs(1,id_edge(id_edge>0)) = i; 26 | edge_regs(2,-id_edge(id_edge<0)) = i; 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/flagnear.m: -------------------------------------------------------------------------------- 1 | function flag = flagnear(obj,pts,opts) 2 | %FLAGNEAR flag points which are within a chunklength (or given factor of 3 | % a chunklength) of any point on each chunk. on return is a sparse 4 | % logical array. If the (i,j) entry is non zero then pts(:,i) is close 5 | % to chunk j in chunkgraph. 6 | % 7 | % Syntax: flag = flagnear(obj,pts,opts) 8 | % 9 | % Input: 10 | % obj - chunkgraph object describing curve 11 | % pts - (obj.dim,nt) array of point coordinates 12 | % 13 | % Optional input: 14 | % opts - options structure 15 | % opts.fac = factor of chunklength to check distance against (1.0) 16 | % 17 | % Output: 18 | % flag - (nt,nch) sparse array. a non zero entry (i,j) means 19 | % that the distance from pts(:,i) to at least one node on 20 | % chunk j is less than opts.fac*length of chunk j. 21 | % where nch is thte total number of chunks int he chunkgraph 22 | % 23 | 24 | % author: Travis Askham (askhawhat@gmail.com) 25 | 26 | chnkrtotal = merge(obj.echnks); 27 | flag = chnkrtotal.flagnear(pts, opts); 28 | 29 | end -------------------------------------------------------------------------------- /chunkie/@chunkgraph/flagnear_rectangle.m: -------------------------------------------------------------------------------- 1 | function flag = flagnear_rectangle(obj,pts,opts) 2 | %FLAGNEAR_RECTANGLE flag points which require special quadrature 3 | % (or given factor of a chunklength) of any point on each chunk. 4 | % On return is a sparse 5 | % logical array. If the (i,j) entry is non zero then pts(:,i) is close 6 | % to chunk j in chnkr. 7 | % 8 | % Syntax: flag = flagnear(obj,pts,opts) 9 | % 10 | % Input: 11 | % obj - chunkgraph object describing curve 12 | % pts - (obj.dim,nt) array of point coordinates 13 | % 14 | % Optional input: 15 | % opts - options structure 16 | % opts.rho = Bernstein ellipse parameter (default=1.8) 17 | % 18 | % Output: 19 | % flag - (nt,nch) sparse array. a non zero entry (i,j) means 20 | % that the distance from pts(:,i) to at least one node on 21 | % chunk j is less than opts.fac*length of chunk j. 22 | % 23 | % Here nch is the total number of chunks in the chunkgraph 24 | % 25 | 26 | 27 | % author: Travis Askham (askhawhat@gmail.com) 28 | 29 | chnkrtotal = merge(obj.echnks); 30 | flag = chnkrtotal.flagnear_rectangle(pts, opts); 31 | 32 | end 33 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/flagnear_rectangle_grid.m: -------------------------------------------------------------------------------- 1 | function flag = flagnear_rectangle_grid(obj,x,y,opts) 2 | %FLAGNEAR_RECTANGLE_GRID flag points which require special quadrature 3 | % (or given factor of a chunklength) of any point on each chunk. 4 | % On return is a sparse logical array. If the (i,j) entry is non zero 5 | % then pts(:,i) is close to chunk j in chnkr. 6 | % 7 | % Syntax: flag = flagnear(obj,pts,opts) 8 | % 9 | % Input: 10 | % obj - chunkgraph object describing curve 11 | % x - nx array of x coordinates for tensor product grid 12 | % y - ny array of y coordinates for tensor product grid 13 | % 14 | % Grid points are interpreted in the order returned by 15 | % MATLAB's meshgrid function [xx,yy] = meshgrid(x,y). 16 | % 17 | % Optional input: 18 | % opts - options structure 19 | % opts.rho = Bernstein ellipse parameter (default=1.8) 20 | % 21 | % Output: 22 | % flag - (nx*ny, nch) sparse array. a non zero entry (i,j) means 23 | % that the distance from pts(:,i) to at least one node on 24 | % chunk j is less than opts.fac*length of chunk j. 25 | % 26 | % Here nch is the total number of chunks on the chunkgraph 27 | % 28 | 29 | % author: Travis Askham (askhawhat@gmail.com) 30 | 31 | chnkrtotal = merge(obj.echnks); 32 | flag = chnkrtotal.flagnear_rectangle_grid(x, y, opts); 33 | 34 | end -------------------------------------------------------------------------------- /chunkie/@chunkgraph/makedatarows.m: -------------------------------------------------------------------------------- 1 | function obj = makedatarows(obj,nrows) 2 | %MAKEDATAROWS add new data rows to chunkgraph object 3 | % 4 | % 5 | % Syntax: obj = makedatarow(obj, nrows); 6 | % 7 | % Input: 8 | % obj - a chunkgraph object 9 | % nrows - number of rows to be added 10 | % 11 | % Output: 12 | % obj - output chunkgraph object with additional data rows 13 | 14 | % 15 | % 16 | if (nrows > 0) 17 | datatemp = obj.data; 18 | datadimold = obj.datadim; 19 | nch = sum(horzcat(obj.echnks.nch)); 20 | obj.data = zeros(datadimold+nrows,obj.k,nch); 21 | obj.data(1:datadimold,:) = datatemp(:,:); 22 | obj.hasdata = true; 23 | else 24 | if (nrows < 0) 25 | warning('attempted to add negative rows, doing nothing'); 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/max.m: -------------------------------------------------------------------------------- 1 | function rmax = max(obj) 2 | %MAX maximum value of each coordinate over chunkgraph nodes 3 | % 4 | % This is *not* the maximum extent of the curve 5 | % 6 | % Syntax: rmax = max(chnkr) 7 | % 8 | % Input: 9 | % chnkr - chunker object 10 | % 11 | % Output: 12 | % rmax - chnkr.dim length vector of maximum node value in each direction 13 | % 14 | % Examples: 15 | % rmax = max(chnkr); 16 | % 17 | 18 | % author: Travis Askham (askhamwhat@gmail.com) 19 | 20 | rmax = max(real(reshape(obj.r,obj.dim,obj.npt)),[],2); -------------------------------------------------------------------------------- /chunkie/@chunkgraph/min.m: -------------------------------------------------------------------------------- 1 | function rmin = min(obj) 2 | %MIN minimum value of each coordinate over chunkgraph nodes 3 | % 4 | % This is *not* the minimum extent of the curve 5 | % 6 | % Syntax: rmin = min(chnkr) 7 | % 8 | % Input: 9 | % chnkr - chunker object 10 | % 11 | % Output: 12 | % rmin - chnkr.dim length vector of minimum node value in each direction 13 | % 14 | % Examples: 15 | % rmin = min(chnkr); 16 | % 17 | 18 | % author: Travis Askham (askhamwhat@gmail.com) 19 | 20 | rmin = min(real(reshape(obj.r,obj.dim,obj.npt)),[],2); -------------------------------------------------------------------------------- /chunkie/@chunkgraph/move.m: -------------------------------------------------------------------------------- 1 | function obj = move(obj, r0, r1, trotat, scale) 2 | %MOVE update the position of chunkers in the chunkgraph by 3 | % translation, rotation, and scaling. 4 | % 5 | % Syntax 6 | % chnkgraph = chnkgraph.move(r0,r1,trotat,scale) 7 | % 8 | % will shift the chunker geometry by -r0, rotate it by angle trotat, 9 | % scale the points by the factor scale, and shift back by +r1, i.e. the 10 | % coordinates will be changed by 11 | % 12 | % r <- s*M*(r-r0) + r1 13 | % 14 | % where M is the rotation matrix for trotat radians and s is the scale 15 | % 16 | % Input: 17 | % r0 - length 2 array, center of rotation. if empty, r0=[0;0] 18 | % r1 - length 2 array, new center. if empty, r1=[0;0] 19 | % trotat - float, angle of rotation in radians. if empty, trotat=0 20 | % scale - float, scaling factor. ifempty, scale = 1 21 | % 22 | % Output: 23 | % chnkr - chunker object with positions, derivatives, normals etc updated 24 | % according to the formula above. 25 | % 26 | 27 | if nargin < 2 || isempty(r0) 28 | r0 = [0;0]; 29 | end 30 | if nargin < 3 || isempty(r1) 31 | r1 = [0;0]; 32 | end 33 | if nargin < 4 || isempty(trotat) 34 | trotat = 0; 35 | end 36 | if nargin < 5 || isempty(scale) 37 | scale = 1; 38 | end 39 | 40 | for i = 1:length(obj.echnks) 41 | obj.echnks(i) = move(obj.echnks(i), r0,r1,trotat,scale); 42 | end 43 | 44 | vsize = size(obj.verts); 45 | 46 | rotmat = [cos(trotat),-sin(trotat);sin(trotat),cos(trotat)]; 47 | 48 | vertsnew = scale*rotmat*(obj.verts(:,:)-r0) + r1; 49 | obj.verts = reshape(vertsnew, vsize); 50 | 51 | 52 | 53 | end 54 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/mtimes.m: -------------------------------------------------------------------------------- 1 | function cg = mtimes(A,cg) 2 | % * Matrix multiplication for chunkgraph. Transforms curve positions by 3 | % r -> A*r and updates derivatives, normals and graph vertices 4 | % accordingly. Note that this routine can change the orientation if 5 | % det(A) is not positive. 6 | 7 | if isa(A,"numeric") && isa(cg,"chunkgraph") 8 | for j = 1:length(cg.echnks) 9 | cg.echnks(j) = A*cg.echnks(j); 10 | end 11 | 12 | if size(cg.verts,2) < 1 13 | return 14 | end 15 | dim = size(cg.verts,1); 16 | if isscalar(A) 17 | A = A*eye(dim); 18 | end 19 | [m,n] = size(A); 20 | if n == dim && m == dim 21 | cg.verts = A*cg.verts; 22 | else 23 | error("CHUNKER:mtimes:invalid",... 24 | "matrix must have compatible size for transforming coordinates"); 25 | end 26 | 27 | cg.wts = weights(cg); 28 | % region stuff needs recomp 29 | cg.vstruc = procverts(cg); 30 | cg.regions = findregions(cg); 31 | 32 | elseif isnumeric(cg) && isscalar(cg) 33 | cg = mtimes(cg,A); 34 | elseif isnumeric(cg) 35 | error("CHUNKER:mtimes:invalid",... 36 | "product of chunkgraph and matrix only defined for matrix on left"); 37 | else 38 | error("CHUNKER:mtimes:invalid",... 39 | "type not supported for product with chunkgraph"); 40 | end -------------------------------------------------------------------------------- /chunkie/@chunkgraph/normals.m: -------------------------------------------------------------------------------- 1 | function rnorms = normals(chnkgrph) 2 | %NORMALS compute normal vectors along boundary of 2D chunkgraph 3 | % 4 | % Syntax: rnorms = normals(cgrph) 5 | % 6 | % Input: 7 | % cgrph - chunkgraph object 8 | % 9 | % Output: 10 | % rnorms - normals along each edge of the cunkgraph 11 | % 12 | % Examples: 13 | % rnorms = normals(cgrph) 14 | % 15 | 16 | % author: Jeremy Hoskins 17 | 18 | % merge the edge chunker objects into a single chunk object 19 | chnkr = merge(chnkgrph.echnks); 20 | assert(chnkr.dim == 2,'normals only implemented for dim=2'); 21 | k = chnkr.k; 22 | nch = chnkr.nch; 23 | d = chnkr.d; 24 | 25 | % compute the normals from the tangent information 26 | dd = sqrt(d(1,:,:).^2 + d(2,:,:).^2); 27 | rnorms = zeros(2,k,nch); 28 | rnorms(1,:,:) = d(2,:,:)./dd; 29 | rnorms(2,:,:) = -d(1,:,:)./dd; 30 | 31 | end 32 | 33 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/normonesmat.m: -------------------------------------------------------------------------------- 1 | function mat = normonesmat(cgrph) 2 | %NORMONESMAT for 2D curves. Forms the matrix for the operator 3 | % 4 | % W[\mu](x) = n(x) \int n(y)\cdot \mu(y) \, dl 5 | % 6 | % which project a vector density (\mu) on the chunker onto the normal 7 | % vector along the chunker. This is a common operator in mechanics for 8 | % removing nullspaces 9 | % 10 | % Syntax: mat = normonesmat(chnkr) 11 | % 12 | % Input: 13 | % cgrph - chunkgraph object 14 | % 15 | % Output: 16 | % mat - the matrix discretization of the operator W above. mat is 17 | % (2*chnkr.npt) x (2*chnkr.npt) 18 | % 19 | % Examples: 20 | % mat = normonesmat(cgrph) 21 | % 22 | % see also ONESMAT 23 | 24 | % author: Travis Askham (askhamwhat@gmail.com) 25 | 26 | wts = cgrph.wts; 27 | rnorms = cgrph.n; 28 | wts = wts(:); 29 | wts2 = repmat(wts.',2,1); 30 | wts2 = wts2(:).*rnorms(:); 31 | 32 | mat = bsxfun(@times,rnorms(:),wts2.'); 33 | 34 | end 35 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/onesmat.m: -------------------------------------------------------------------------------- 1 | function mat = onesmat(cgrph) 2 | %ONESMAT Forms the matrix for the operator 3 | % 4 | % W[\mu](x) = \int \mu(y) dl 5 | % 6 | % which projects a scalar density (\mu) on the chunker onto the constant 7 | % vector along the chunker. This is a common operator for removing 8 | % nullspaces 9 | % 10 | % Syntax: mat = onesmat(chnkr) 11 | % 12 | % Input: 13 | % cgrph - chunkgraph object 14 | % 15 | % Output: 16 | % mat - the matrix discretization of the operator W above. mat is 17 | % (cgrph.npt) x (cgrph.npt) 18 | % 19 | % Examples: 20 | % mat = onesmat(chnkr) 21 | % 22 | % see also NORMONESMAT 23 | 24 | % author: Travis Askham (askhamwhat@gmail.com) 25 | 26 | wts = cgrph.wts; 27 | wts = wts(:); 28 | temp = ones(size(wts)); 29 | mat = bsxfun(@times,temp,wts.'); 30 | 31 | end 32 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/plot.m: -------------------------------------------------------------------------------- 1 | function plot(obj,varargin) 2 | %Plot plots chunkgraph in 2 dimensions 3 | % Uses standard plot commands. All edges in the chunkgraph are 4 | % plotted in a different color. 5 | % 6 | % Syntax: plot(cgrph,varargin) 7 | % 8 | % Input: 9 | % cgrph - chunkgraph object 10 | % varargin - any of the standard plot commands 11 | % 12 | % Output: 13 | % none 14 | % 15 | % Examples: 16 | % plot(cgrph,'r','LineWidth',2) % plot of chunkgraph normals 17 | % % with thick red arrows 18 | 19 | 20 | % author: Jeremy Hoskins 21 | 22 | ifhold = ishold(); 23 | 24 | echnks = obj.echnks; 25 | 26 | hold on 27 | for i=1:numel(echnks) 28 | plot(echnks(i),varargin{:}); 29 | end 30 | 31 | hold off 32 | 33 | if ifhold 34 | hold on 35 | end -------------------------------------------------------------------------------- /chunkie/@chunkgraph/plus.m: -------------------------------------------------------------------------------- 1 | function g = plus(f,g) 2 | % + pointwise addition for chunkgraph class 3 | % 4 | % Currently only supported for adding a constant vector to the chunkgraph, 5 | % translating the entire object 6 | 7 | if ~isa(g,'chunkgraph') 8 | g = plus(g,f); 9 | elseif isa(f,'numeric') 10 | for j = 1:numel(g.echnks) 11 | g.echnks(j) = f(:) + g.echnks(j); 12 | end 13 | if (size(g.verts,2) < 1) 14 | return 15 | end 16 | assert(numel(f) == size(g.verts,1),... 17 | 'CHUNKGRAPH:plus vector must have same dimension as chunkgraph points'); 18 | g.verts = f(:) + g.verts; 19 | else 20 | error('CHUNKGRAPH:plus:invalid', ... 21 | 'plus only defined for sum of an appropriate size vector and chunkgraph object'); 22 | end -------------------------------------------------------------------------------- /chunkie/@chunkgraph/procverts.m: -------------------------------------------------------------------------------- 1 | function vstruc = procverts(obj) 2 | %PROCVERTS for each vertex in a chunkgraph object, sorts the edges 3 | % connecting to that vertex in counterclockwise order. The results are 4 | % stored in a struct. 5 | % 6 | % Syntax: vstruc = procverts(cgrph); 7 | % 8 | % Input: 9 | % cgrph - chunkgraph object 10 | % 11 | % Output: 12 | % vstruc - a cell array with one cell per each vertex in the 13 | % chunkgrph. Each cell consists of a list of edge numbers 14 | % which terminate at that vertex, and a vector of signs 15 | % which are positive if the corresponding edge ends at the 16 | % vertex and negative if the edge begins at the vertex. 17 | % 18 | % 19 | % 20 | 21 | % author: Jeremy Hoskins 22 | 23 | verts = obj.verts; 24 | vstruc = {}; 25 | 26 | % loop over all the vertices and call vertextract 27 | for i=1:size(verts,2) 28 | [inds,isgn] = vertextract(i,obj); 29 | vstruc{i} = {inds,isgn}; 30 | end 31 | 32 | end 33 | 34 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/quiver.m: -------------------------------------------------------------------------------- 1 | function quiver(obj,varargin) 2 | %QUIVER quiver plot of chunkgraph normal vectors in 2 dimensions 3 | % Uses standard quiver commands. All edges in the chunkgraph will be 4 | % plotted in a different color. 5 | % 6 | % Syntax: quiver(cgrph,varargin) 7 | % 8 | % Input: 9 | % cgrph - chunkgraph object 10 | % varargin - any of the standard quiver commands 11 | % 12 | % Output: 13 | % none 14 | % 15 | % Examples: 16 | % quiver(cgrph,'r','LineWidth',2) % quiver plot of chunkgraph normals 17 | % % with thick red arrows 18 | % 19 | % see also PLOT, PLOT3 20 | 21 | % author: Jeremy Hoskins 22 | 23 | ifhold = ishold(); 24 | 25 | hold on 26 | 27 | for i=1:numel(obj.echnks) 28 | quiver(obj.echnks(i),varargin{:}); 29 | end 30 | 31 | hold off 32 | 33 | if ifhold 34 | hold on 35 | end 36 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/reflect.m: -------------------------------------------------------------------------------- 1 | function cg = reflect(cg,theta,r0,r1) 2 | %REFLECT reflect chunkgraph object across line specified by angle 3 | % 4 | % Syntax 5 | % cg = cg.reflect(theta,r0,r1); 6 | % 7 | % will shift the chunkgraph geometry by -r0, reflect it across the line 8 | % spanned by [cos(theta); sin(theta)] and shift back by +r1, i.e. the 9 | % coordinates will be changed by 10 | % 11 | % r <- M*(r-r0) + r1 12 | % 13 | % where M is the reflection matrix [cos(2*theta) sin(2*theta); sin(2*theta) 14 | % -cos(2*theta)] 15 | % 16 | % Input: 17 | % theta - float, angle made by reflection axis in radians. if empty, 18 | % theta=0 19 | % r0 - length 2 array, center of reflection if empty, r0=[0;0] 20 | % r1 - length 2 array, new center. if empty, r1=[0;0] 21 | % 22 | % Output: 23 | % cg - chunkgraph object with positions, derivatives, normals etc updated 24 | % according to the formula above. 25 | % 26 | 27 | if nargin < 3 || isempty(r0) 28 | r0 = [0;0]; 29 | end 30 | if nargin < 4 || isempty(r1) 31 | r1 = [0;0]; 32 | end 33 | 34 | assert(isreal(theta),"reflect only supports real angles"); 35 | 36 | for j = 1:length(cg.echnks) 37 | cg.echnks(j) = cg.echnks(j).reflect(theta,r0,r1); 38 | end 39 | 40 | c = cos(2*theta); 41 | s = sin(2*theta); 42 | refmat = [c s; s -c]; 43 | 44 | cg.verts = refmat*(cg.verts-r0) + r1; 45 | 46 | % region stuff needs recomp 47 | cg.vstruc = procverts(cg); 48 | cg.regions = findregions(cg); 49 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/rotate.m: -------------------------------------------------------------------------------- 1 | function cg = rotate(cg,theta,r0,r1) 2 | %ROTATE rotate chunkgraph object by specified angle 3 | % 4 | % Syntax 5 | % cg = cg.rotate(theta,r0,r1); 6 | % 7 | % will shift the chunkgraph geometry by -r0, rotate it by angle trotat, 8 | % and shift back by +r1, i.e. the coordinates will be changed by 9 | % 10 | % r <- M*(r-r0) + r1 11 | % 12 | % where M is the rotation matrix for theta radians 13 | % 14 | % Input: 15 | % theta - float, angle of rotation in radians. if empty, trotat=0 16 | % r0 - length 2 array, center of rotation. if empty, r0=[0;0] 17 | % r1 - length 2 array, new center. if empty, r1=[0;0] 18 | % 19 | % Output: 20 | % cg - chunkgraph object with positions, derivatives, normals etc updated 21 | % according to the formula above. 22 | % 23 | 24 | if nargin < 3 || isempty(r0) 25 | r0 = [0;0]; 26 | end 27 | if nargin < 4 || isempty(r1) 28 | r1 = [0;0]; 29 | end 30 | 31 | assert(isreal(theta),"rotate only supports real angles"); 32 | 33 | for j = 1:length(cg.echnks) 34 | cg.echnks(j) = cg.echnks(j).rotate(theta,r0,r1); 35 | end 36 | 37 | c = cos(theta); 38 | s = sin(theta); 39 | rotmat = [c -s; s c]; 40 | 41 | cg.verts = rotmat*(cg.verts-r0) + r1; -------------------------------------------------------------------------------- /chunkie/@chunkgraph/scatter.m: -------------------------------------------------------------------------------- 1 | function scatter(obj,varargin) 2 | %SCATTER scatter plot of the coordinates of the chunkgraph object. 3 | % Must be a 2D chunkgraph. Faster than plot --> no sorting required 4 | % Uses standard scatter commands 5 | % 6 | % Syntax: scatter(obj,varargin) 7 | % 8 | % Input: 9 | % obj - chunkgraph object 10 | % varargin - any of the scatter commands 11 | % 12 | % Output: 13 | % none 14 | % 15 | % Examples: 16 | % scatter(obj,'ro') % scatter plot of chunkgraph points as red circles 17 | % 18 | % see also PLOT 19 | 20 | % author: Travis Askham (askhamwhat@gmail.com) 21 | 22 | assert(obj.dim == 2,'for scatter plot must be 2D chunkgraph'); 23 | xs = obj.r(1,:,:); xs = xs(:); 24 | ys = obj.r(2,:,:); ys = ys(:); 25 | 26 | scatter(xs,ys,varargin{:}); -------------------------------------------------------------------------------- /chunkie/@chunkgraph/signed_curvature.m: -------------------------------------------------------------------------------- 1 | function kappa = signed_curvature(cgrph) 2 | %CURVATURE returns the signed curvature at each node 3 | % 4 | % (x'y'' - y'x'')/(x'^2+y'^2)^(3/2) 5 | % 6 | 7 | assert(size(cgrph.r,1) == 2,'signed curvature only defined in 2D'); 8 | kappa = (cgrph.d(1,:).*cgrph.d2(2,:)- ... 9 | cgrph.d(2,:).*cgrph.d2(1,:))./(sqrt(sum(cgrph.d(:,:).^2,1)).^3); 10 | nch = sum(horzcat(cgrph.echnks.nch)); 11 | kappa = reshape(kappa,cgrph.k,nch); 12 | end -------------------------------------------------------------------------------- /chunkie/@chunkgraph/slicegraph.m: -------------------------------------------------------------------------------- 1 | function cgrph = slicegraph(cgrph, ichs) 2 | %SLICEGRAPH extract edges of cgrph corresponding to cgrph.echnks(ichs) 3 | 4 | % get the edges to keep 5 | edgesendverts = cgrph.edgesendverts(:,ichs); 6 | 7 | % get the vertices to keep 8 | iverts = 1:size(cgrph.verts,2); 9 | iverts = iverts(ismember(iverts, edgesendverts)); 10 | 11 | verts = cgrph.verts(:, iverts); 12 | 13 | % update vertex indices 14 | edgesendvertsnew = edgesendverts; 15 | for i = 1:size(verts,2) 16 | edgesendvertsnew(edgesendverts==iverts(i)) = i; 17 | end 18 | 19 | % assemble the sliced graph 20 | cgrph.verts = verts; 21 | cgrph.edgesendverts = edgesendvertsnew; 22 | cgrph.v2emat = build_v2emat(cgrph); 23 | cgrph.echnks = cgrph.echnks(ichs); 24 | cgrph.vstruc = procverts(cgrph); 25 | cgrph.wts = weights(cgrph); 26 | 27 | cgrph.regions = findregions(cgrph); 28 | end -------------------------------------------------------------------------------- /chunkie/@chunkgraph/tangents.m: -------------------------------------------------------------------------------- 1 | function ts = tangents(cgrph) 2 | %TANGENTS return unit tangent vectors along the chunkers in the chunkgraph 3 | % 4 | % Syntax: ts = tangents(cgrph) 5 | % 6 | % Input: 7 | % cgrph - chunkgraph object 8 | % 9 | % Output: 10 | % ts - unit tangent vector along curve 11 | % 12 | % Examples: 13 | % ts = tangents(chnkr); 14 | % 15 | 16 | % author: Travis Askham (askhamwhat@gmail.com) 17 | 18 | d = cgrph.d; 19 | 20 | dd = sqrt(sum(abs(d).^2,1)); 21 | ts = bsxfun(@rdivide,cgrph.d,dd); 22 | 23 | end 24 | 25 | -------------------------------------------------------------------------------- /chunkie/@chunkgraph/weights.m: -------------------------------------------------------------------------------- 1 | function wts = weights(chnkgrph) 2 | %WEIGHTS integration weights suitable for smooth functions defined on the 3 | % chunkgraph object 4 | % 5 | % This is merely the standard Legendre weights scaled to the chunks 6 | % 7 | % Syntax: wts = weights(chnkgrph) 8 | % 9 | % Input: 10 | % chnkgrph - chunkgraph object 11 | % 12 | % Output: 13 | % wts - smooth integration weights 14 | % 15 | % Examples: 16 | % wts = weights(chnkgraph) 17 | % 18 | 19 | % author: Jeremy Hoskins 20 | 21 | 22 | % merge the edge chunks to a single chunk object 23 | chnkr = merge(chnkgrph.echnks); 24 | wts = chnkr.wts; 25 | 26 | end 27 | -------------------------------------------------------------------------------- /chunkie/@kernel/minus.m: -------------------------------------------------------------------------------- 1 | function f = minus(f,g) 2 | % - Pointwise subtraction for kernel class 3 | % 4 | % Currently only supported for subtracting two kernel class objects. 5 | 6 | if (isa(g,'kernel') && isa(f,'kernel')) 7 | assert(f.opdims(1) == g.opdims(1) && f.opdims(2) == g.opdims(2), ... 8 | 'kernel dimensions must agree to add'); 9 | f.name = ['custom ',f.name,' ',g.name]; 10 | 11 | if(isa(f.shifted_eval, 'function_handle')) 12 | if(isa(g.shifted_eval, 'function_handle')) 13 | f.shifted_eval = @(varargin) f.shifted_eval(varargin{:})-g.shifted_eval(varargin{:}); 14 | else 15 | f.shifted_eval = @(varargin) f.shifted_eval(varargin{:})-g.eval(varargin{1:2}); 16 | end 17 | else 18 | if(isa(g.shifted_eval, 'function_handle')) 19 | f.shifted_eval = @(varargin) f.eval(varargin{1:2})-g.shifted_eval(varargin{:}); 20 | else 21 | f.shifted_eval = []; 22 | end 23 | end 24 | 25 | f.eval = @(varargin) f.eval(varargin{:}) - g.eval(varargin{:}); 26 | if (isa(g.fmm,'function_handle') && isa(f.fmm,'function_handle')) 27 | f.fmm = @(varargin) f.fmm(varargin{:}) - g.fmm(varargin{:}); 28 | else 29 | f.fmm = []; 30 | end 31 | 32 | if or(f.isnan,g.isnan) 33 | f = kernel.nans(f.opdims(1),f.opdims(2)); 34 | end 35 | if and(f.iszero,g.iszero) 36 | f.iszero = true; 37 | else 38 | f.iszero = false; 39 | end 40 | else 41 | error('KERNEL:minus:invalid', ... 42 | 'F and G must be kernel class objects'); 43 | end 44 | end 45 | 46 | -------------------------------------------------------------------------------- /chunkie/@kernel/mrdivide.m: -------------------------------------------------------------------------------- 1 | function f = mrdivide(f,g) 2 | % * Matrix right division for kernel 3 | % 4 | % Currently only supports scalars 5 | % 6 | % returns c*F or F*C for the kernel F and scalar c 7 | f = rdivide(f,g); 8 | end 9 | -------------------------------------------------------------------------------- /chunkie/@kernel/mtimes.m: -------------------------------------------------------------------------------- 1 | function f = mtimes(f,g) 2 | % * Matrix multiplication for kernel 3 | % 4 | % Currently only supports scalars 5 | % 6 | % returns c*F or F*C for the kernel F and scalar c 7 | f = times(f,g); 8 | end 9 | -------------------------------------------------------------------------------- /chunkie/@kernel/nans.m: -------------------------------------------------------------------------------- 1 | function obj = nans(m, n) 2 | %KERNEL.NAN Construct the nan kernel. 3 | % KERNEL.NAN() constructs the nan kernel with operator dimensions 4 | % of 1 x 1. 5 | % 6 | % KERNEL.NAN(N) constructs the nan kernel with operator dimensions 7 | % of N x N. 8 | % 9 | % KERNEL.NAN(M, N) constructs the NAN kernel with operator dimensions 10 | % of M x N. 11 | 12 | if ( nargin < 1 ) 13 | m = 1; 14 | end 15 | 16 | if ( nargin < 2 ) 17 | n = m; 18 | end 19 | 20 | function out = eval_(s, t) 21 | [~, ns] = size(s.r); 22 | [~, nt] = size(t.r); 23 | out = nan(m*nt, n*ns); 24 | end 25 | 26 | function out = shifted_eval_(s, t, o) 27 | [~, ns] = size(s.r); 28 | [~, nt] = size(t.r); 29 | out = nan(m*nt, n*ns); 30 | end 31 | 32 | function varargout = fmm_(eps, s, t, sigma) 33 | 34 | if ( isstruct(t) ) 35 | [~, nt] = size(t.r); 36 | else 37 | [~, nt] = size(t); 38 | end 39 | 40 | if ( nargout > 0 ), varargout{1} = nan(m*nt, 1); end 41 | if ( nargout > 1 ), varargout{2} = nan(2, m*nt); end 42 | if ( nargout > 2 ), varargout{3} = nan(3, m*nt); end 43 | if ( nargout > 3 ) 44 | error('CHUNKIE:kernel:nan', 'Too many output arguments for FMM.'); 45 | end 46 | 47 | end 48 | 49 | obj = kernel(); 50 | obj.name = 'nans'; 51 | obj.opdims = [m n]; 52 | obj.sing = 'smooth'; 53 | obj.eval = @eval_; 54 | obj.shifted_eval = @shifted_eval_; 55 | obj.fmm = @fmm_; 56 | obj.isnan = true; 57 | 58 | end 59 | -------------------------------------------------------------------------------- /chunkie/@kernel/plus.m: -------------------------------------------------------------------------------- 1 | function f = plus(f,g) 2 | % + Pointwise addition for kernel class 3 | % 4 | % Currently only supported for adding two kernel class objects. 5 | 6 | if (isa(g,'kernel') && isa(f,'kernel')) 7 | assert(f.opdims(1) == g.opdims(1) && f.opdims(2) == g.opdims(2), ... 8 | 'kernel dimensions must agree to add'); 9 | f.name = ['custom ',f.name,' ',g.name]; 10 | 11 | if(isa(f.shifted_eval, 'function_handle')) 12 | if(isa(g.shifted_eval, 'function_handle')) 13 | f.shifted_eval = @(varargin) f.shifted_eval(varargin{:})+g.shifted_eval(varargin{:}); 14 | else 15 | f.shifted_eval = @(varargin) f.shifted_eval(varargin{:})+g.eval(varargin{1:2}); 16 | end 17 | else 18 | if(isa(g.shifted_eval, 'function_handle')) 19 | f.shifted_eval = @(varargin) f.eval(varargin{1:2})+g.shifted_eval(varargin{:}); 20 | else 21 | f.shifted_eval = []; 22 | end 23 | end 24 | 25 | f.eval = @(varargin) g.eval(varargin{:}) + f.eval(varargin{:}); 26 | if (isa(g.fmm,'function_handle') && isa(f.fmm,'function_handle')) 27 | f.fmm = @(varargin) g.fmm(varargin{:}) + f.fmm(varargin{:}); 28 | else 29 | f.fmm = []; 30 | end 31 | 32 | if or(f.isnan,g.isnan) 33 | f = kernel.nans(f.opdims(1),f.opdims(2)); 34 | end 35 | if and(f.iszero,g.iszero) 36 | f.iszero = true; 37 | else 38 | f.iszero = false; 39 | end 40 | else 41 | error('KERNEL:plus:invalid', ... 42 | 'F and G must be kernel class objects'); 43 | end 44 | end 45 | 46 | -------------------------------------------------------------------------------- /chunkie/@kernel/rdivide.m: -------------------------------------------------------------------------------- 1 | function f = rdivide(f,g) 2 | % ./ Pointwise division of kernel class 3 | % 4 | % Currently only supported for f a kernel and g a numeric scalar 5 | % 6 | % f./g returns a kernel class object where each of the function 7 | % handles - eval, and fmm are divided by g 8 | 9 | if (isnumeric(g) && isscalar(g)) 10 | if(isa(f.eval, 'function_handle')) 11 | f.eval = @(varargin) f.eval(varargin{:})/g; 12 | else 13 | f.eval = []; 14 | end 15 | 16 | if(isa(f.shifted_eval, 'function_handle')) 17 | f.shifted_eval = @(varargin) f.shifted_eval(varargin{:})/g; 18 | else 19 | f.shifted_eval = []; 20 | end 21 | 22 | if(isa(f.fmm, 'function_handle')) 23 | f.fmm = @(varargin) f.fmm(varargin{:}).g; 24 | else 25 | f.fmm = []; 26 | end 27 | 28 | if or(f.isnan,isnan(g)) 29 | f = kernel.nans(f.opdims(1),f.opdims(2)); 30 | end 31 | if ~f.isnan && g==0 || f.iszero && ~isnan(g) 32 | f = kernel.zeros(f.opdims(1),f.opdims(2)); 33 | end 34 | 35 | else 36 | error('KERNEL:rdivide:invalid', ... 37 | 'F must be a kernel class object and G a scalar'); 38 | end 39 | end 40 | 41 | -------------------------------------------------------------------------------- /chunkie/@kernel/times.m: -------------------------------------------------------------------------------- 1 | function f = times(f,g) 2 | % .* Pointwise multiplication for kernel class 3 | % 4 | % Currently only supported for scalars, if g is a numeric scalar 5 | % then f.*g or g.*f returns a kernel class object where each 6 | % of the function handles - eval, and fmm are multiplied by g 7 | 8 | if (~isa(f,'kernel')) 9 | f = times(g,f); 10 | return 11 | elseif (isnumeric(g) && isscalar(g)) 12 | if(isa(f.eval, 'function_handle')) 13 | f.eval = @(varargin) g*f.eval(varargin{:}); 14 | else 15 | f.eval = []; 16 | end 17 | 18 | if(isa(f.shifted_eval, 'function_handle')) 19 | f.shifted_eval = @(varargin) g*f.shifted_eval(varargin{:}); 20 | else 21 | f.shifted_eval = []; 22 | end 23 | 24 | if(isa(f.fmm, 'function_handle')) 25 | f.fmm = @(varargin) g*f.fmm(varargin{:}); 26 | else 27 | f.fmm = []; 28 | end 29 | 30 | if or(f.isnan,isnan(g)) 31 | f = kernel.nans(f.opdims(1),f.opdims(2)); 32 | end 33 | if ~f.isnan && g==0 || f.iszero && ~isnan(g) 34 | f = kernel.zeros(f.opdims(1),f.opdims(2)); 35 | end 36 | 37 | else 38 | error('KERNEL:times:invalid', ... 39 | 'F or G must be constant and the other a kernel class object'); 40 | end 41 | end 42 | 43 | -------------------------------------------------------------------------------- /chunkie/@kernel/uminus.m: -------------------------------------------------------------------------------- 1 | function f = uminus(f) 2 | % multiply a kernel class by negative 1 3 | % 4 | 5 | if(isa(f.shifted_eval, 'function_handle')) 6 | f.shifted_eval = @(varargin) -f.shifted_eval(varargin{:}); 7 | else 8 | f.shifted_eval = []; 9 | 10 | end 11 | 12 | f.eval = @(varargin) - f.eval(varargin{:}); 13 | 14 | if (isa(f.fmm,'function_handle')) 15 | f.fmm = @(varargin) -f.fmm(varargin{:}); 16 | else 17 | f.fmm = []; 18 | end 19 | 20 | end 21 | 22 | 23 | -------------------------------------------------------------------------------- /chunkie/@kernel/zeros.m: -------------------------------------------------------------------------------- 1 | function obj = zeros(m, n) 2 | %KERNEL.ZEROS Construct the zero kernel. 3 | % KERNEL.ZEROS() constructs the zero kernel with operator dimensions 4 | % of 1 x 1. 5 | % 6 | % KERNEL.ZEROS(N) constructs the zero kernel with operator dimensions 7 | % of N x N. 8 | % 9 | % KERNEL.ZEROS(M, N) constructs the zero kernel with operator dimensions 10 | % of M x N. 11 | 12 | if ( nargin < 1 ) 13 | m = 1; 14 | end 15 | 16 | if ( nargin < 2 ) 17 | n = m; 18 | end 19 | 20 | function out = eval_(s, t) 21 | [~, ns] = size(s.r); 22 | [~, nt] = size(t.r); 23 | out = zeros(m*nt, n*ns); 24 | end 25 | 26 | function out = shifted_eval_(s, t, o) 27 | [~, ns] = size(s.r); 28 | [~, nt] = size(t.r); 29 | out = zeros(m*nt, n*ns); 30 | end 31 | 32 | function varargout = fmm_(eps, s, t, sigma) 33 | 34 | if ( isstruct(t) ) 35 | [~, nt] = size(t.r); 36 | else 37 | [~, nt] = size(t); 38 | end 39 | 40 | if ( nargout > 0 ), varargout{1} = zeros(m*nt, 1); end 41 | if ( nargout > 1 ), varargout{2} = zeros(2, m*nt); end 42 | if ( nargout > 2 ), varargout{3} = zeros(3, m*nt); end 43 | if ( nargout > 3 ) 44 | error('CHUNKIE:kernel:zeros', 'Too many output arguments for FMM.'); 45 | end 46 | 47 | end 48 | 49 | obj = kernel(); 50 | obj.name = 'zeros'; 51 | obj.opdims = [m n]; 52 | obj.sing = 'smooth'; 53 | obj.eval = @eval_; 54 | obj.shifted_eval = @shifted_eval_; 55 | obj.fmm = @fmm_; 56 | obj.iszero = true; 57 | 58 | end 59 | -------------------------------------------------------------------------------- /chunkie/@trapper/arclength.m: -------------------------------------------------------------------------------- 1 | function s = arclength(chnkr) 2 | 3 | %s = bsxfun(@rdivide,squeeze(sum((chnkr.d).^2,1)),chnkr.h(:).'); 4 | s = squeeze(sum((chnkr.d).^2,1)); 5 | 6 | end -------------------------------------------------------------------------------- /chunkie/@trapper/area.m: -------------------------------------------------------------------------------- 1 | function a = area(trap) 2 | %AREA compute area of a closed, 2D trapper curve 3 | 4 | assert(trap.dim == 2,'area only well-defined for 2d curves'); 5 | 6 | wts = trap.wts; 7 | rnorm = trap.n; 8 | a = sum(sum(wts.*sum(rnorm.*(trap.r),1)))/trap.dim; 9 | 10 | end 11 | -------------------------------------------------------------------------------- /chunkie/@trapper/max.m: -------------------------------------------------------------------------------- 1 | function rmax = max(obj) 2 | 3 | rmax = max(reshape(obj.r,obj.dim,obj.k*obj.nch),[],2); -------------------------------------------------------------------------------- /chunkie/@trapper/min.m: -------------------------------------------------------------------------------- 1 | function rmin = min(obj) 2 | 3 | rmin = min(reshape(obj.r,obj.dim,obj.k*obj.nch),[],2); -------------------------------------------------------------------------------- /chunkie/@trapper/normals.m: -------------------------------------------------------------------------------- 1 | function rnorms = normals(trap) 2 | 3 | assert(trap.dim == 2,'normals only well-defined for dim=2'); 4 | 5 | d = trap.d; 6 | 7 | dd = sqrt(d(1,:,:).^2 + d(2,:,:).^2); 8 | rnorms = zeros(2,trap.npt); 9 | rnorms(1,:) = d(2,:)./dd; 10 | rnorms(2,:) = -d(1,:)./dd; 11 | 12 | end 13 | 14 | -------------------------------------------------------------------------------- /chunkie/@trapper/normonesmat.m: -------------------------------------------------------------------------------- 1 | function normonesmat = normonesmat(trap) 2 | 3 | wts = trap.wts; 4 | rnorms = trap.n; 5 | wts = wts(:); 6 | wts2 = repmat(wts.',2,1); 7 | wts2 = wts2(:).*rnorms(:); 8 | 9 | normonesmat = bsxfun(@times,rnorms(:),wts2.'); 10 | 11 | end 12 | -------------------------------------------------------------------------------- /chunkie/@trapper/onesmat.m: -------------------------------------------------------------------------------- 1 | function onesmat = onesmat(trap) 2 | 3 | wts = weights(trap); 4 | wts = wts(:); 5 | temp = ones(size(wts)); 6 | onesmat = bsxfun(@times,temp,wts.'); 7 | 8 | end 9 | -------------------------------------------------------------------------------- /chunkie/@trapper/plot.m: -------------------------------------------------------------------------------- 1 | function plot(obj,varargin) 2 | %PLOT plot the coordinates of the trapper object 3 | % Must be a 2D trapper 4 | 5 | assert(obj.dim == 2,'for plot must be 2D trapper'); 6 | 7 | xs = obj.r(1,:); ys = obj.r(2,:); 8 | xs = [xs, xs(1)]; ys = [ys, ys(1)]; 9 | plot(xs,ys,varargin{:}) -------------------------------------------------------------------------------- /chunkie/@trapper/quiver.m: -------------------------------------------------------------------------------- 1 | function quiver(obj,varargin) 2 | %QUIVER quiver plot of chunker normal vectors in 2 dimensions 3 | 4 | assert(obj.dim == 2,'for quiver plot must be 2D chunker'); 5 | 6 | xs = obj.r(1,:); xs = xs(:); 7 | ys = obj.r(2,:); ys = ys(:); 8 | 9 | rnorms = normals(obj); 10 | 11 | u = rnorms(1,:); u = u(:); 12 | v = rnorms(2,:); v = v(:); 13 | 14 | quiver(xs,ys,u,v,varargin{:}); -------------------------------------------------------------------------------- /chunkie/@trapper/reverse.m: -------------------------------------------------------------------------------- 1 | function obj = reverse(obj) 2 | %REVERSE reverses the orientation of the trapper object 3 | % 4 | 5 | obj.r = obj.r(:,end:-1:1); 6 | obj.d = -obj.d(:,end:-1:1); 7 | obj.d2 = obj.d2(:,end:-1:1); 8 | 9 | end -------------------------------------------------------------------------------- /chunkie/@trapper/scatter.m: -------------------------------------------------------------------------------- 1 | function scatter(obj,varargin) 2 | %SCATTER scatter plot of the coordinates of the trapper object. 3 | % Must be a 2D trapper 4 | % 5 | % see also SCATTER3 6 | 7 | assert(obj.dim == 2,'for scatter plot must be 2D trapper'); 8 | xs = obj.r(1,:); xs = xs(:); 9 | ys = obj.r(2,:); ys = ys(:); 10 | 11 | scatter(xs,ys,varargin{:}); -------------------------------------------------------------------------------- /chunkie/@trapper/taus.m: -------------------------------------------------------------------------------- 1 | function tau = taus(trap) 2 | 3 | d = trap.d; 4 | 5 | dd = sqrt(sum(abs(d).^2,1)); 6 | tau = bsxfun(@rdivide,trap.d,dd); 7 | 8 | end 9 | 10 | -------------------------------------------------------------------------------- /chunkie/@trapper/weights.m: -------------------------------------------------------------------------------- 1 | function wts = weights(trap) 2 | %WEIGHTS - note that this routine must only be used in the 3 | % constructor 4 | 5 | wts = sqrt(sum((trap.d).^2,1)); 6 | wts = wts*trap.h; 7 | 8 | end 9 | -------------------------------------------------------------------------------- /chunkie/@trapper/whts.m: -------------------------------------------------------------------------------- 1 | function wts = whts(trap) 2 | 3 | warning('whts is deprecated, will be removed. use weights instead'); 4 | 5 | wts = sqrt(sum((trap.d).^2,1)); 6 | wts = wts*trap.h; 7 | 8 | end 9 | -------------------------------------------------------------------------------- /chunkie/@trapperpref/trapperpref.m: -------------------------------------------------------------------------------- 1 | classdef trapperpref 2 | %TRAPPERPREF class for storing preferences for trapper objects and 3 | % sets defaults 4 | 5 | properties 6 | dim 7 | nptstor 8 | nptmax 9 | end 10 | 11 | methods 12 | function obj = trapperpref(pref) 13 | %TRAPPERPREF construct trapperpref from either a given 14 | % trapperpref or struct listing properties to set 15 | 16 | assert(nargin <= 1,'number of arguments must be 0 or 1'); 17 | defpref = trapperpref.defaultprefs(); 18 | if nargin < 1 || isempty(pref) 19 | pref = defpref; 20 | end 21 | assert(or(isempty(pref),or(isstruct(pref),isa(pref,'trapperpref'))), ... 22 | 'bad input, must be empty, a struct, or a trapperpref object'); 23 | if isa(pref,'trapperpref') 24 | % do nothing if input is a trapperpref 25 | obj = pref; 26 | else 27 | deffields = fieldnames(defpref); 28 | fields = fieldnames(pref); 29 | 30 | % assign defaults first, then overwrite 31 | for i = 1:length(deffields) 32 | obj.(deffields{i}) = defpref.(deffields{i}); 33 | end 34 | for i = 1:length(fields) 35 | obj.(fields{i}) = pref.(fields{i}); 36 | end 37 | end 38 | end 39 | end 40 | methods (Static) 41 | function defpref = defaultprefs() 42 | defpref = []; 43 | defpref.nptstor = 10000; 44 | defpref.nptmax = 1000000; 45 | defpref.dim = 2; 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /chunkie/checkcurveparam.m: -------------------------------------------------------------------------------- 1 | function dim = checkcurveparam(fcurve,ta,nout) 2 | %CHECKCURVEPARAM check if a curve parameterization is correctly formatted 3 | % and return the dimension of the curve. 4 | % 5 | % Warning: this does *not* check that the derivatives are correct 6 | % 7 | % Syntax: dim = checkcurveparam(fcurve,ta) 8 | % 9 | % Input: 10 | % fcurve - function handle of the form 11 | % r = fcurve(t); 12 | % where r is a size [dim,size(t)] arrays describing 13 | % the position of a curve in dim dimensions parameterized by t. 14 | % 15 | % optionally, the function can be of the form 16 | % [r,d] = fcurve(t); or [r,d,d2] = fcurve(t); 17 | % where d is the first derivative of r with respect to t and 18 | % d2 is the second derivative. 19 | % ta - sample point t in parameterization to test 20 | % nout - number of outputs of fcurve 21 | % 22 | % Output: 23 | % dim - the dimension of the curve 24 | % 25 | % Examples: 26 | % dim = checkcurveparam(@(t) starfish(t),0.0); 27 | 28 | 29 | if nargin < 3 30 | nout = 3; 31 | end 32 | 33 | out = cell(nout,1); 34 | [out{:}] = fcurve(ta); 35 | 36 | dims = zeros(nout,1); 37 | 38 | for i = 1:nout 39 | sz = size(out{i}); 40 | dims(i) = sz(1); 41 | assert(prod(sz(2:end)) == numel(ta), ... 42 | 'size of each curve output should match input'); 43 | end 44 | 45 | dim = dims(1); 46 | assert(all(dims == dim),'dimension of curve output should be consistent'); 47 | -------------------------------------------------------------------------------- /chunkie/chunkgraphinit.m: -------------------------------------------------------------------------------- 1 | function [cgrph] = chunkgraphinit(verts,edge2verts,fchnks,cparams) 2 | 3 | warning('This method is deprecated. Use the chunkgraph constructor instead.'); 4 | 5 | cgrph = chunkgraph(verts,edge2verts,fchnks,cparams); 6 | 7 | end 8 | -------------------------------------------------------------------------------- /chunkie/demo/addpaths_loc.m: -------------------------------------------------------------------------------- 1 | function addpaths_loc() 2 | 3 | run('../../startup.m'); 4 | -------------------------------------------------------------------------------- /chunkie/demo/demo_concentric_domain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/demo/demo_concentric_domain.png -------------------------------------------------------------------------------- /chunkie/demo/demo_concentric_fields.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/demo/demo_concentric_fields.png -------------------------------------------------------------------------------- /chunkie/demo/demo_data_field.m: -------------------------------------------------------------------------------- 1 | % A simple test to show data fields being used with a kernel. 2 | % The hilbert kernel used here requires an arclength parameterization as 3 | % input, which must be input as a data field. 4 | k = 2; 5 | 6 | % Make a non-circular chnkr 7 | chnkr = chunkerfunc(@(t) [5.*(cos(t))'; (sin(t))'],cparams,pref); 8 | % Make a data field for the Hilbert kernel 9 | chnkr = chnkr.makedatarows(1); 10 | L = sum(sum(chnkr.wts)); 11 | data_tmp = arclengthfun(chnkr)/L; 12 | chnkr.data(:) = data_tmp(:)*pi; 13 | 14 | H_mat = chunkermat(chnkr, H_kernel())/L; % The L normalization is necessary 15 | 16 | f_1 = sin(2*k*chnkr.data(:)); %data goes from 0 to pi, so k must be even 17 | f_2 = H_mat*f_1; % H_mat should change sin to cos for well-resolved frequencies k. 18 | 19 | %This should be zero 20 | norm(f_1.^2 + f_2.^2 - 1) 21 | 22 | function ck = H_kernel() 23 | ck = kernel(); 24 | ck.name = "cotan"; 25 | ck.type = "cot"; 26 | ck.eval = @(s, t) cot_func(s, t); 27 | ck.opdims = [1,1]; 28 | ck.sing = 'pv'; 29 | 30 | end 31 | 32 | function val = cot_func(s, t) 33 | theta = (t.data(:)) - (s.data(:).'); 34 | val = cot(theta); 35 | end 36 | -------------------------------------------------------------------------------- /chunkie/demo/demo_mixed_bc.m: -------------------------------------------------------------------------------- 1 | %DEMO MIXED BOUNDARY VALUE PROBLEM 2 | % 3 | % This code illustrates the solution of the Laplace equation 4 | % with mixed boundary conditions. The domain is a star-shaped 5 | % domain where the radius has 5 Fourier modes, and the Dirichlet 6 | % part of the boundary corresponds to y>0, and the Neumann 7 | % part of the boundary corresponds to y<0. The boundary 8 | % data itself is given by a Fourier series in x 9 | % BEGIN DEMO MIXED BC 10 | %% Define geometry 11 | narms = 5; 12 | amp = 0.3; 13 | 14 | verts = [1+amp, -1+amp; 0, 0]; 15 | fchnks = @(t) starfish(t, narms, amp); 16 | cparams = cell(2,1); 17 | cparams{1}.ta = 0; 18 | cparams{1}.tb = pi; 19 | cparams{1}.maxchunklen = 0.1; 20 | cparams{2}.ta = -pi; 21 | cparams{2}.tb = 0; 22 | cparams{2}.maxchunklen = 0.1; 23 | edgesendverts = [1 2; 2 1]; 24 | 25 | cgrph = chunkgraph(verts, edgesendverts, fchnks, cparams); 26 | 27 | %% Setup kernels 28 | S = 2*kernel('lap', 's'); 29 | D = (-2)*kernel('lap', 'd'); 30 | Sp = 2*kernel('lap', 'sprime'); 31 | Dp = (-2)*kernel('lap', 'dprime'); 32 | 33 | K(2,2) = kernel(); 34 | K(1,1) = D; 35 | K(1,2) = S; 36 | K(2,1) = Dp; 37 | K(2,2) = Sp; 38 | 39 | Keval(1,2) = kernel(); 40 | Keval(1,1) = D; 41 | Keval(1,2) = S; 42 | 43 | %% Build matrix 44 | A = chunkermat(cgrph, K); 45 | A = A + eye(size(A,1)); 46 | 47 | %% Build test boundary data; 48 | rhs = zeros(cgrph.npt,1); 49 | npt1 = cgrph.echnks(1).npt; 50 | 51 | rng(1); 52 | rhs(1:npt1) = real(exp(1j*40*cgrph.echnks(1).r(1,:))*exp(1j*2*pi*rand)).'; 53 | rhs(npt1+1:end) = real(exp(1j*43*cgrph.echnks(2).r(1,:))*exp(1j*2*pi*rand)).'; 54 | 55 | sig = A \ rhs; 56 | 57 | %% Postprocess 58 | % define targets 59 | x1 = linspace(-1-amp,1+amp,300); 60 | [xx,yy] = meshgrid(x1,x1); 61 | targs = [xx(:).'; yy(:).']; 62 | 63 | % identify points in computational domain 64 | in = chunkerinterior(cgrph,{x1,x1}); 65 | 66 | uu = chunkerkerneval(cgrph, Keval, sig, targs); 67 | u = nan(size(xx(:))); 68 | u(in) = uu(in); 69 | 70 | figure(1) 71 | clf 72 | plot(cgrph, 'LineWidth', 2); 73 | hold on; 74 | pcolor(xx, yy, reshape(u, size(xx))); shading interp 75 | axis equal tight 76 | % END DEMO MIXED BC 77 | saveas(figure(1),"mixed_bc_plot.png") 78 | -------------------------------------------------------------------------------- /chunkie/demo/demo_neumann_combined_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/demo/demo_neumann_combined_plot.png -------------------------------------------------------------------------------- /chunkie/demo/mixed_bc_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/demo/mixed_bc_plot.png -------------------------------------------------------------------------------- /chunkie/demo/planewave.m: -------------------------------------------------------------------------------- 1 | function [y] = planewave(kvec,r) 2 | 3 | y=exp(1i*sum(bsxfun(@times,kvec(:),r(:,:)))); -------------------------------------------------------------------------------- /chunkie/ellipse.m: -------------------------------------------------------------------------------- 1 | function [r, d, d2] = ellipse(t,varargin) 2 | %ELLIPSE return position, first and second derivatives of an ellipse 3 | % with the parameterization 4 | % 5 | % x(t) = a*cos(t) 6 | % y(t) = b*sin(t) 7 | % 8 | % Syntax: [r,d,d2] = ellipse(t,a,b) 9 | % 10 | % Input: 11 | % t - array of points (in [0,2pi]) 12 | % 13 | % Optional input: 14 | % a - xscaling 15 | % b - xscaling 16 | % 17 | % Output: 18 | % r - 2 x numel(t) array of positions, r(:,i) = [x(t(i)); y(t(i))] 19 | % d - 2 x numel(t) array of t derivative of r 20 | % d2 - 2 x numel(t) array of second t derivative of r 21 | % 22 | % Examples: 23 | % [r,d,d2] = ellipse(t); % circle parameterization 24 | % [r,d,d2] = ellipse(t,a,b); % stretch circle into ellipse 25 | % 26 | a = 1; 27 | b = 1; 28 | if nargin > 1 && ~isempty(varargin{1}) 29 | a = varargin{1}; 30 | end 31 | if nargin > 2 && ~isempty(varargin{2}) 32 | b = varargin{2}; 33 | end 34 | 35 | r = [ a*cos(t(:).'); b*sin(t(:).')]; 36 | d = [-a*sin(t(:).'); b*cos(t(:).')]; 37 | d2 = [-a*cos(t(:).');-b*sin(t(:).')]; 38 | 39 | 40 | 41 | end -------------------------------------------------------------------------------- /chunkie/guide/addpaths_loc.m: -------------------------------------------------------------------------------- 1 | function addpaths_loc() 2 | 3 | run('../../startup.m'); 4 | -------------------------------------------------------------------------------- /chunkie/guide/expkernel.m: -------------------------------------------------------------------------------- 1 | function mat = expkernel(s,t,k) 2 | %EXPKERNEL this implements the kernel evaluator function for the 3 | % kernel exp(ik|x-y|) in the chunkIE kernel format as part of the 4 | % chunkIE guide 5 | % 6 | % Syntax: 7 | % mat = expkernel(s,t,k) 8 | % 9 | 10 | xs = s.r(1,:); 11 | ys = s.r(2,:); 12 | xt = t.r(1,:); 13 | yt = t.r(2,:); 14 | 15 | mat = exp(1i*k*sqrt((xt.'-xs).^2+(yt.'-ys).^2)); 16 | -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkers_barbell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkers_barbell.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkers_bymode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkers_bymode.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkers_chunkerfit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkers_chunkerfit.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkers_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkers_circle.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkers_interior.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkers_interior.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkers_shiftandreverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkers_shiftandreverse.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkers_starfish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkers_starfish.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkgraphs_curved_edges.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkgraphs_curved_edges.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkgraphs_hawaiian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkgraphs_hawaiian.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkgraphs_polygon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkgraphs_polygon.png -------------------------------------------------------------------------------- /chunkie/guide/guide_chunkgraphs_regions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_chunkgraphs_regions.png -------------------------------------------------------------------------------- /chunkie/guide/guide_simplebvps_basicscattering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_simplebvps_basicscattering.png -------------------------------------------------------------------------------- /chunkie/guide/guide_simplebvps_laplaceneumann.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_simplebvps_laplaceneumann.png -------------------------------------------------------------------------------- /chunkie/guide/guide_stokesvelocity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/chunkie/guide/guide_stokesvelocity.png -------------------------------------------------------------------------------- /chunkie/guide/planewave.m: -------------------------------------------------------------------------------- 1 | function [y] = planewave(kvec,r) 2 | 3 | y=exp(1i*sum(bsxfun(@times,kvec(:),r(:,:)))); -------------------------------------------------------------------------------- /chunkie/mergeregions.m: -------------------------------------------------------------------------------- 1 | function [rgnout] = mergeregions(cgrph,rgn1,rgn2) 2 | 3 | rgnout = {}; 4 | 5 | e2 = rgn2{1}{1}(1); 6 | v2 = cgrph.edgesendverts(2,abs(e2)); 7 | v2 = cgrph.verts(:,v2); 8 | 9 | irgn = 0; 10 | for ii=2:numel(rgn1) 11 | nin = pointinregion(cgrph,rgn1{ii},v2); 12 | if (nin > 0 && mod(nin,2)==1) 13 | if (irgn ~= 0) 14 | disp("Warning: an unsupported geometry error has occurred"); 15 | end 16 | irgn = ii; 17 | end 18 | end 19 | 20 | if (irgn ~= 0) 21 | rgnout = rgn1; 22 | rgnout = [rgnout,rgn2(2:end)]; 23 | rgnout{irgn} = [rgnout{irgn},rgn2{1}]; 24 | end 25 | 26 | irgn1 = irgn; 27 | 28 | if (irgn == 0) 29 | e1 = rgn1{1}{1}(1); 30 | v1 = cgrph.edgesendverts(2,abs(e1)); 31 | v1 = cgrph.verts(:,v1); 32 | 33 | irgn = 0; 34 | for ii=2:numel(rgn2) 35 | nin = pointinregion(cgrph,rgn2{ii},v1); 36 | if (nin > 0 && mod(nin,2)==1) 37 | if (irgn ~= 0) 38 | disp("Warning: an unsupported geometry error has occurred"); 39 | end 40 | irgn = ii; 41 | end 42 | end 43 | 44 | if (irgn ~= 0) 45 | rgnout = rgn2; 46 | rgnout = [rgnout,rgn1(2:end)]; 47 | rgnout{irgn} = [rgnout{irgn},rgn1{1}]; 48 | end 49 | end 50 | 51 | if (irgn1==0 && irgn==0) 52 | rgnout = rgn1; 53 | rgnout = [rgnout,rgn2(2:end)]; 54 | rgnout{1} = [rgnout{1},rgn2{1}]; 55 | end 56 | 57 | end 58 | 59 | -------------------------------------------------------------------------------- /chunkie/nonflatinterface.m: -------------------------------------------------------------------------------- 1 | function [r,d,d2] = nonflatinterface(t,a,b,c,d) 2 | %NONFLATINTERFACE curve parameterization of a perturbed interface given as 3 | % the graph (x(t),y(t)) = (t,d e^(-at^2/2) sin(bt+c)) 4 | % 5 | % Syntax: 6 | % [r,d,d2] = nonflatinterface(t,a,b,c,d) 7 | % 8 | % Input: 9 | % t - array of t parameter values where curve coordinates 10 | % are desired 11 | % a,b,c,d - curve parameters as in formula above 12 | % 13 | % Output: 14 | % r,d,d2 - 2 x numel(t) arrays of position, first and second 15 | % derivatives at desired t parameter values 16 | % 17 | 18 | % author: Solomon Quinn 19 | 20 | xs = t; 21 | xp = ones(size(t)); 22 | xpp = zeros(size(t)); 23 | 24 | 25 | ys = d*exp(-a*t.^2/2).*sin(b*t+c); 26 | yp = d*exp(-a*t.^2/2).*(b*cos(b*t+c) - a*t.*sin(b*t+c)); 27 | ypp = d*exp(-a*t.^2/2).*(-2*a*b*t.*cos(b*t+c) + (a*a*t.^2-a-b^2).*sin(b*t+c)); 28 | 29 | r = [(xs(:)).'; (ys(:)).']; 30 | d = [(xp(:)).'; (yp(:)).']; 31 | d2 = [(xpp(:)).'; (ypp(:)).']; 32 | end 33 | -------------------------------------------------------------------------------- /chunkie/pointinregion.m: -------------------------------------------------------------------------------- 1 | function [nin] = pointinregion(cgrph,rgn,r0) 2 | nin = 0; 3 | for ii=1:numel(rgn) 4 | iedges = rgn{ii}; 5 | rs = []; 6 | for jj=1:numel(iedges) 7 | rtmp = sort(cgrph.echnks(abs(iedges(jj)))).r(:,:); 8 | if (iedges(jj)<0) 9 | rtmp = fliplr(rtmp(:,:)); 10 | end 11 | rs = [rs,rtmp]; 12 | end 13 | [in] = inpolygon(r0(1),r0(2),rs(1,:),rs(2,:)); 14 | if (in == 1) 15 | nin = nin + 1; 16 | end 17 | end 18 | end 19 | 20 | -------------------------------------------------------------------------------- /chunkie/regioninside.m: -------------------------------------------------------------------------------- 1 | function [isinside] = regioninside(cgrph,rgn1,rgn2) 2 | 3 | e2 = rgn2{1}{1}(1); 4 | v2 = cgrph.edgesendverts(2,abs(e2)); 5 | v2 = cgrph.verts(:,v2); 6 | irgn = 0; 7 | for ii=2:numel(rgn1) 8 | nin = pointinregion(cgrph,rgn1{ii},v2); 9 | if (nin > 0 && mod(nin,2)==1) 10 | if (irgn ~= 0) 11 | disp("Warning: an unsupported geometry error has occurred"); 12 | end 13 | irgn = ii; 14 | end 15 | end 16 | isinside = (irgn ~=0); 17 | end 18 | 19 | -------------------------------------------------------------------------------- /chunkie/starfish.m: -------------------------------------------------------------------------------- 1 | 2 | function [r,d,d2] = starfish(t,varargin) 3 | %STARFISH return position, first and second derivatives of a starfish 4 | % domain with the parameterization 5 | % 6 | % x(t) = x0 + (1+amp*cos(narms*(t+phi)))*cos(t) 7 | % y(t) = y0 + (1+amp*cos(narms*(t+phi)))*sin(t) 8 | % 9 | % Syntax: [r,d,d2] = starfish(t,narms,amp,ctr,phi,scale) 10 | % 11 | % Input: 12 | % t - array of points (in [0,2pi]) 13 | % 14 | % Optional input: 15 | % narms - integer, number of arms on starfish (5) 16 | % amp - float, amplitude of starfish arms relative to radius of length 1 17 | % (0.3) 18 | % ctr - float(2), x0,y0 coordinates of center of starfish ( [0,0] ) 19 | % phi - float, phase shift (0) 20 | % scale - scaling factor (1.0) 21 | % 22 | % Output: 23 | % r - 2 x numel(t) array of positions, r(:,i) = [x(t(i)); y(t(i))] 24 | % d - 2 x numel(t) array of t derivative of r 25 | % d2 - 2 x numel(t) array of second t derivative of r 26 | % 27 | % Examples: 28 | % [r,d,d2] = starfish(t); % get default settings 29 | % [r,d,d2] = starfish(t,narms,[],ctr,[],scale); % change some settings 30 | % 31 | 32 | narms = 5; 33 | amp = 0.3; 34 | x0 = 0.0; 35 | y0 = 0.0; 36 | phi = 0.0; 37 | scale = 1.0; 38 | if nargin > 1 && ~isempty(varargin{1}) 39 | narms = varargin{1}; 40 | end 41 | if nargin > 2 && ~isempty(varargin{2}) 42 | amp = varargin{2}; 43 | end 44 | if nargin > 3 && ~isempty(varargin{3}) 45 | ctr = varargin{3}; 46 | x0 = ctr(1); y0 = ctr(2); 47 | end 48 | if nargin > 4 && ~isempty(varargin{4}) 49 | phi = varargin{4}; 50 | end 51 | if nargin > 5 && ~isempty(varargin{5}) 52 | scale = varargin{5}; 53 | end 54 | 55 | 56 | fvals = zeros(length(t),6); 57 | ct = cos(t); 58 | st = sin(t); 59 | cnt = cos(narms*(t+phi)); 60 | snt = sin(narms*(t+phi)); 61 | 62 | xs = x0+(1+amp*cnt).*ct*scale; 63 | ys = y0+(1+amp*cnt).*st*scale; 64 | dxs = -(1+amp*cnt).*st-narms*amp*snt.*ct; 65 | dxs = dxs*scale; 66 | dys = (1+amp*cnt).*ct-narms*amp*snt.*st; 67 | dys = dys*scale; 68 | d2xs = -dys-narms*amp*(narms*cnt.*ct-snt.*st); 69 | d2xs = d2xs*scale; 70 | d2ys = dxs-narms*amp*(narms*cnt.*st+snt.*ct); 71 | d2ys = d2ys*scale; 72 | 73 | r = [(xs(:)).'; (ys(:)).']; 74 | d = [(dxs(:)).'; (dys(:)).']; 75 | d2 = [(d2xs(:)).'; (d2ys(:)).']; 76 | 77 | end 78 | 79 | -------------------------------------------------------------------------------- /chunkie/trapperfunc.m: -------------------------------------------------------------------------------- 1 | function trap = trapperfunc(fcurve,cparams,pref) 2 | %TRAPFUNC discretize a curve using uniform points in 3 | % parameter space. 4 | % 5 | % cparams = curve parameters (default value) 6 | % 7 | % cparams.ta = left end of t interval (0) 8 | % cparams.tb = right end of t interval (2*pi) 9 | % cparams.npt = number of points to use (100) 10 | % 11 | % See also TRAPPER 12 | 13 | 14 | if nargin < 2 15 | cparams = []; 16 | end 17 | 18 | ta = 0.0; tb = 2*pi; 19 | npt = 100; 20 | 21 | if isfield(cparams,'ta') 22 | ta = cparams.ta; 23 | end 24 | if isfield(cparams,'tb') 25 | tb = cparams.tb; 26 | end 27 | if isfield(cparams,'npt') 28 | npt = cparams.npt; 29 | end 30 | 31 | dim = checkcurveparam(fcurve,ta); 32 | 33 | if nargin < 3 34 | p = []; p.dim = dim; 35 | pref = trapperpref(p); 36 | else 37 | pref = trapperpref(pref); 38 | end 39 | 40 | 41 | assert(pref.dim == dim); 42 | 43 | 44 | nout = 3; 45 | out = cell(nout,1); 46 | 47 | trap = trapper(pref); 48 | trap = trap.addpt(npt); 49 | 50 | h = (tb-ta)/npt; 51 | ts = ta + (0:(npt-1))*h; 52 | 53 | [rs,ds,d2s] = fcurve(ts); 54 | trap.r = rs; 55 | trap.d = ds; 56 | trap.d2 = d2s; 57 | trap.h = h; 58 | trap.n = normals(trap); 59 | 60 | end 61 | 62 | 63 | -------------------------------------------------------------------------------- /chunkie/trapperkerneval.m: -------------------------------------------------------------------------------- 1 | function fints = trapperkerneval(trap,kern,dens,targobj,opts) 2 | %TRAPPERINTKERN compute the convolution of the integral kernel with 3 | 4 | wts = trap.wts; 5 | srcinfo = []; srcinfo.r = trap.r; srcinfo.d = trap.d; srcinfo.d2 = trap.d2; 6 | srcinfo.n = trap.n; 7 | 8 | % Assign appropriate object to targinfo 9 | targinfo = []; 10 | if isa(targobj, "trapper") 11 | targinfo.r = targobj.r(:,:); 12 | targinfo.d = targobj.d(:,:); 13 | targinfo.d2 = targobj.d2(:,:); 14 | targinfo.n = targobj.n(:,:); 15 | else 16 | targinfo.r = targobj; 17 | end 18 | 19 | mat = kern(srcinfo,targinfo); 20 | fints = mat*diag(wts)*dens; 21 | 22 | end 23 | -------------------------------------------------------------------------------- /devtools/docstyle/template_header.m: -------------------------------------------------------------------------------- 1 | function [output1,output2] = function_name(input1,input2,input3) 2 | %FUNCTION_NAME - One line description of what the function or script performs (H1 line) 3 | %Optional file header info (to give more details about the function than in the H1 line) 4 | %Optional file header info (to give more details about the function than in the H1 line) 5 | %Optional file header info (to give more details about the function than in the H1 line) 6 | % 7 | % Syntax: [output1,output2] = function_name(input1,input2,input3) 8 | % 9 | % Inputs: 10 | % input1 - Description 11 | % input2 - Description 12 | % input3 - Description 13 | % 14 | % Outputs: 15 | % output1 - Description 16 | % output2 - Description 17 | % 18 | % Example: 19 | % Line 1 of example 20 | % Line 2 of example 21 | % Line 3 of example 22 | % 23 | % Other m-files required: none 24 | % Subfunctions: none 25 | % MAT-files required: none 26 | % 27 | % See also: OTHER_FUNCTION_NAME1, OTHER_FUNCTION_NAME2 28 | 29 | % Author: FirstName FamilyName 30 | % Work address 31 | % email: 32 | % Website: http://www. 33 | % May 2004; Last revision: 12-May-2004 34 | 35 | %------------- BEGIN CODE -------------- 36 | 37 | Enter your executable matlab commands here 38 | 39 | %------------- END OF CODE -------------- 40 | %Please send suggestions for improvement of the above template header 41 | %to Denis Gilbert at this email address: gilbertd@dfo-mpo.gc.ca. 42 | %Your contribution towards improving this template will be acknowledged in 43 | %the "Changes" section of the TEMPLATE_HEADER web page on the Matlab 44 | %Central File Exchange 45 | -------------------------------------------------------------------------------- /devtools/docstyle/template_header_license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004, Denis Gilbert 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 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /devtools/test/absconvgaussTest.m: -------------------------------------------------------------------------------- 1 | absconvgaussTest0(); 2 | 3 | 4 | function absconvgaussTest0() 5 | %ABSCONVGAUSSTEST 6 | % 7 | % This file tests the absconvgauss routine 8 | 9 | a = 0.75; 10 | 11 | b = -0.75; 12 | m = b/a; 13 | 14 | 15 | fabs = @(x) m*abs(x); 16 | nplot = 1000; 17 | ntest = 10; 18 | 19 | h = b/m/8.0; 20 | offset = 0.0; 21 | 22 | % xplot = linspace(-a,a,nplot); 23 | % 24 | % figure(1) 25 | % clf 26 | % plot(xplot,fabs(xplot),'r') 27 | % hold on 28 | % plot(xplot,chnk.spcl.absconvgauss(xplot,m,offset,h)); 29 | % 30 | % figure(2) 31 | % clf 32 | % ff = chnk.spcl.absconvgauss(xplot,m,offset,h); 33 | % df = abs(ff-fabs(xplot)); 34 | % semilogy(df); 35 | 36 | xtest = linspace(-a/2,a/2,ntest); 37 | pert = 0.1*b/m; 38 | 39 | ifprint = false; 40 | niter = 6; 41 | for i = 1:ntest 42 | x0 = xtest(i); 43 | errsf= gradient_check(@(x) chnk.spcl.absconvgauss(x,m,offset,h),... 44 | x0,pert,niter,ifprint); 45 | errsg = gradient_check(@(x) ... 46 | acgder(x,m,offset,h),x0,pert,niter,ifprint); 47 | assert(min(errsf) < 1e-8); 48 | assert(min(errsg) < 1e-6); 49 | end 50 | 51 | 52 | 53 | end 54 | 55 | 56 | function [d,d2] = acgder(x,a,b,h) 57 | [~,d,d2] = chnk.spcl.absconvgauss(x,a,b,h); 58 | end 59 | -------------------------------------------------------------------------------- /devtools/test/arclengthfunTest.m: -------------------------------------------------------------------------------- 1 | arclengthfunTest0(); 2 | 3 | 4 | function arclengthfunTest0() 5 | %ARCLENGTHFUNTEST tests the arclengthfun routine for computing distance 6 | % along length of curve 7 | % 8 | 9 | seed = 8675309; 10 | rng(seed); 11 | 12 | % geometry parameters and construction 13 | 14 | 15 | cparams = []; 16 | cparams.eps = 1.0e-9; 17 | pref = []; 18 | pref.k = 16; 19 | narms = 0; 20 | amp = 0.0; 21 | start = tic; chnkr = chunkerfunc(@(t) starfish(t,narms,amp),cparams,pref); 22 | 23 | [s, ~, chnkr] = arclengthfun(chnkr); 24 | % Compare to analytic arclength for circle 25 | ts = squeeze(atan2(chnkr.r(2,:,:), chnkr.r(1,:,:))); 26 | ts(ts<0) = ts(ts<0) + 2*pi; 27 | assert(norm(s-ts) < 1e-12); 28 | 29 | % Now test two circles 30 | chnkrs(2) = chunker(); 31 | chnkrs(1) = chnkr; 32 | rfac = 1.1; 33 | chnkrs(2) = move(chnkr, [0;0], [3;0], 0, rfac); 34 | chnkrtotal = merge(chnkrs); 35 | [s, nchs, ~] = arclengthfun(chnkrtotal); 36 | 37 | assert(norm(s(:,1:nchs(1)) - ts) < 1e-12); 38 | assert(norm(s(:,nchs(1)+1:end) - rfac*ts) < 1e-12); 39 | 40 | 41 | end 42 | 43 | 44 | -------------------------------------------------------------------------------- /devtools/test/chunker_diffintmatTest.m: -------------------------------------------------------------------------------- 1 | chunker_diffintmatTest0(); 2 | 3 | function chunker_diffintmatTest0() 4 | chnkr = chunkerfunc(@(t) [cos(t)'; 5*sin(t)']); 5 | 6 | D = diffmat(chnkr); 7 | C = intmat(chnkr); 8 | 9 | dx = D * chnkr.r(1,:).'; 10 | dy = D * chnkr.r(2,:).'; 11 | 12 | % Check that (dx, dy) are unit tangent vectors 13 | assert(vecnorm(dx.^2 + dy.^2 - 1) < 1e-10); 14 | 15 | x = C * dx; 16 | y = C * dy; 17 | 18 | % Check that integral and derivative are inverse up to a scalar 19 | assert(vecnorm(x - x(1) - chnkr.r(1,:).' + chnkr.r(1,1)) < 1e-10); 20 | assert(vecnorm(y - y(1) - chnkr.r(2,:).' + chnkr.r(2,1)) < 1e-10); 21 | 22 | chnkr = chunkerfunc(@(t) [cos(t)'; sin(t)']); 23 | D = diffmat(chnkr); 24 | test_quant = D * chnkr.r(1,:).' + chnkr.r(2,:).'; 25 | assert(vecnorm(test_quant) < 1e-10); 26 | 27 | end -------------------------------------------------------------------------------- /devtools/test/chunker_nearestTest.m: -------------------------------------------------------------------------------- 1 | chunker_nearestTest0(); 2 | 3 | 4 | function chunker_nearestTest0() 5 | %chunker.nearest test 6 | % 7 | 8 | iseed = 1234; 9 | rng(iseed); 10 | 11 | % compare closest computed point on circle geometry to exact answer 12 | 13 | circ = chunkerfunc(@(t) chnk.curves.bymode(t,1)); 14 | nt = 1000; 15 | thetas = -pi+2*pi*rand(1,nt); 16 | 17 | % the 0.1 here keeps targets away from coordinate singularity of circle 18 | scal = 0.1+2*rand(1,nt); 19 | targs = [cos(thetas); sin(thetas)].*scal; 20 | 21 | for j = 1:nt 22 | [rn,dn,dist,tn,ichn] = nearest(circ,targs(:,j)); 23 | th1 = atan2(targs(2,j),targs(1,j)); 24 | th2 = atan2(rn(2),rn(1)); 25 | err = min(abs(th1-th2),abs(th1-th2+2*pi)); 26 | err = min(err,abs(th1-th2-2*pi)); 27 | assert(err < 1e-12); 28 | end 29 | 30 | end 31 | 32 | 33 | -------------------------------------------------------------------------------- /devtools/test/chunkerclassunitTest.m: -------------------------------------------------------------------------------- 1 | chunkerclassunitTest0(); 2 | 3 | 4 | function chunkerclassunitTest0() 5 | %chunkerclassunitTest 6 | % 7 | % setting up some tests for methods of the chunker class 8 | % 9 | 10 | % adversarial constructor tests 11 | isuccess = 0; 12 | try 13 | pref = []; pref.k = -1; 14 | chnkr = chunker(pref); 15 | catch 16 | isuccess = 1; 17 | end 18 | assert(isuccess); 19 | 20 | isuccess = 0; 21 | try 22 | pref = []; pref.k = 9; [t,w] = lege.exps(8); 23 | chnkr = chunker(pref,t,w); 24 | catch 25 | isuccess = 1; 26 | end 27 | assert(isuccess); 28 | 29 | isuccess = 0; 30 | try 31 | cparams = []; 32 | pref = []; pref.k=4; pref.nchmax = 100; 33 | chnkr = chunkerfunc(@(t) starfish(t),cparams,pref); 34 | catch 35 | isuccess = 1; 36 | end 37 | assert(isuccess); 38 | 39 | cparams = []; cparams.chsmall = 1e-14; cparams.ifclosed=0; 40 | cparams.tb = 2*pi-0.01; cparams.nover=1; 41 | pref = []; pref.k=16; pref.nchmax = 10000; 42 | chnkr = chunkerfunc(@(t) starfish(t),cparams,pref); 43 | 44 | 45 | for j = 1:chnkr.nch 46 | i1 = chnkr.adj(1,j); 47 | i2 = chnkr.adj(2,j); 48 | if (i1 > 0) 49 | assert(chnkr.adj(2,i1) == j) 50 | end 51 | if (i2 > 0) 52 | assert(chnkr.adj(1,i2) == j) 53 | end 54 | end 55 | 56 | % test transforms 57 | v = [1;2]; 58 | com1 = chnkr.r(:,:)*chnkr.wts(:)/sum(chnkr.wts(:)); 59 | chnkr2 = v + chnkr; 60 | com2 = chnkr2.r(:,:)*chnkr2.wts(:)/sum(chnkr2.wts(:)); 61 | assert(norm(v-(com2-com1))/norm(v) < 1e-14) 62 | chnkr2 = chnkr + v; % add on either side 63 | com2 = chnkr2.r(:,:)*chnkr2.wts(:)/sum(chnkr2.wts(:)); 64 | assert(norm(v-(com2-com1))/norm(v) < 1e-14) 65 | 66 | A = [1 2; 2 3]; 67 | chnkr2 = A*chnkr; 68 | assert(abs(area(chnkr2) - det(A)*area(chnkr))/abs(area(chnkr)) < 1e-14); 69 | s = 2; 70 | chnkr2 = s*chnkr; 71 | assert(abs(area(chnkr2) - s^2*area(chnkr))/abs(area(chnkr)) < 1e-14); 72 | chnkr2 = chnkr*s; % scale on either side 73 | assert(abs(area(chnkr2) - s^2*area(chnkr))/abs(area(chnkr)) < 1e-14); 74 | 75 | caught = false; 76 | try 77 | chnkr2 = chnkr*A; % only transform by matrix on left 78 | catch 79 | caught = true; 80 | end 81 | assert(caught); 82 | 83 | end 84 | 85 | 86 | -------------------------------------------------------------------------------- /devtools/test/chunkerfitTest.m: -------------------------------------------------------------------------------- 1 | chunkerfitTest0(); 2 | 3 | 4 | function chunkerfitTest0() 5 | 6 | %CHUNKERFITTEST 7 | 8 | 9 | % Sample a smooth curve at random points 10 | rng(0) 11 | n = 20; 12 | tt = sort(2*pi*rand(n,1)); 13 | r = chnk.curves.bymode(tt, [2 0.5 0.2 0.7]); 14 | 15 | opts = []; 16 | opts.ifclosed = true; 17 | opts.cparams = []; 18 | opts.cparams.eps = 1e-6; 19 | opts.pref = []; 20 | opts.pref.k = 16; 21 | chnkr = chunkerfit(r, opts); 22 | assert(checkadjinfo(chnkr) == 0); 23 | 24 | opts.ifclosed = false; 25 | chnkr = chunkerfit(r(:,1:10), opts); 26 | assert(checkadjinfo(chnkr) == 0); 27 | 28 | 29 | end 30 | 31 | 32 | -------------------------------------------------------------------------------- /devtools/test/chunkerfuncuniTest.m: -------------------------------------------------------------------------------- 1 | chunkerfuncuniTest0(); 2 | 3 | 4 | function chunkerfuncuniTest0() 5 | 6 | %CHNKFUNCUNITEST 7 | % 8 | % This file tests the routine chunkerfunc on a couple of examples 9 | % as well as testing the plot, quiver, sort, and reverse utilities 10 | 11 | 12 | nch = 10; 13 | 14 | narms = 3; 15 | amp = 0.5; 16 | start = tic; chnkr = chunkerfuncuni(@(t) starfish(t,narms,amp),nch); 17 | t1 = toc(start); 18 | 19 | % 20 | 21 | fprintf('%5.2e seconds to chunk starfish with %d chunks\n',t1,chnkr.nch); 22 | 23 | figure(1) 24 | clf 25 | subplot(1,2,1) 26 | plot(chnkr) 27 | hold on 28 | quiver(chnkr) 29 | axis equal 30 | 31 | % 32 | 33 | modes = randn(11,1); modes(1) = 1.1*sum(abs(modes(2:end))); ctr = [1.0;-0.5]; 34 | 35 | start = tic; chnkr = chunkerfuncuni(@(t) chnk.curves.bymode(t,modes,ctr),nch); 36 | t1 = toc(start); 37 | 38 | fprintf('%5.2e seconds to chunk random mode domain with %d chunks\n', ... 39 | t1,chnkr.nch); 40 | 41 | chnkr = reverse(chnkr); 42 | 43 | subplot(1,2,2) 44 | plot(chnkr) 45 | hold on 46 | quiver(chnkr) 47 | axis equal 48 | 49 | 50 | % chunk up circle and test area 51 | 52 | r = 5*rand(); ctr = [1.0;-0.5]; 53 | 54 | circfun = @(t) ctr + r*[cos(t(:).');sin(t(:).')]; 55 | 56 | start = tic; chnkr = chunkerfuncuni(circfun,nch); 57 | t1 = toc(start); 58 | 59 | fprintf('%5.2e seconds to chunk circle domain with %d chunks\n', ... 60 | t1,chnkr.nch); 61 | 62 | [~,~,info] = sortinfo(chnkr); 63 | assert(info.ier == 0,'adjacency issues after chunk build circle'); 64 | 65 | a = area(chnkr); 66 | assert(abs(a - pi*r^2) < 1e-12,'area wrong for circle domain') 67 | 68 | 69 | 70 | 71 | end 72 | 73 | 74 | -------------------------------------------------------------------------------- /devtools/test/chunkerintegralTest.m: -------------------------------------------------------------------------------- 1 | chunkerintegralTest0(); 2 | 3 | 4 | function chunkerintegralTest0() 5 | %CHUNKERINTEGRALTEST test the routines for integrating over chunks 6 | % 7 | % 8 | 9 | 10 | seed = 8675309; 11 | rng(seed); 12 | 13 | % geometry parameters and construction 14 | 15 | cparams = []; 16 | cparams.eps = 1.0e-4; 17 | pref = []; 18 | pref.k = 16; 19 | narms = 5; 20 | amp = 0.5; 21 | chnkr = chunkerfunc(@(t) starfish(t,narms,amp),cparams); 22 | 23 | 24 | % scalar function on boundary 25 | 26 | fscal = @(xx) cos(xx(1,:)-1.0) + sin(xx(2,:)-0.5); 27 | fvals = fscal(reshape(chnkr.r,2,chnkr.k*chnkr.nch)); 28 | opts = []; 29 | opts.quadgkparams = {'RelTol',1e-15}; 30 | opts.usesmooth = false; 31 | fscal_int1 = chunkerintegral(chnkr,fvals,opts); 32 | opts.usesmooth = true; 33 | fscal_int3 = chunkerintegral(chnkr,fvals,opts); 34 | 35 | opts.usesmooth = false; 36 | fscal_int2 = chunkerintegral(chnkr,fscal,opts); 37 | opts.usesmooth = true; 38 | fscal_int4 = chunkerintegral(chnkr,fscal,opts); 39 | 40 | assert(abs(fscal_int1-fscal_int2)/abs(fscal_int2) < 1e-9); 41 | assert(abs(fscal_int3-fscal_int2)/abs(fscal_int2) < 1e-9); 42 | assert(abs(fscal_int4-fscal_int2)/abs(fscal_int2) < 1e-9); 43 | 44 | end 45 | 46 | 47 | -------------------------------------------------------------------------------- /devtools/test/chunkerkerneval_correctionsTest.m: -------------------------------------------------------------------------------- 1 | chunkerkerneval_correctionsTest0(); 2 | 3 | 4 | function chunkerkerneval_correctionsTest0() 5 | 6 | seed = 8675309; 7 | rng(seed); 8 | 9 | % geometry parameters and construction 10 | 11 | cparams = []; 12 | cparams.eps = 1.0e-11; 13 | pref = []; 14 | pref.k = 16; 15 | narms = 5; 16 | amp = 0.5; 17 | start = tic; chnkr = chunkerfunc(@(t) starfish(t,narms,amp),cparams,pref); 18 | t1 = toc(start); 19 | 20 | ns = 10; 21 | ts = 0.0+2*pi*rand(ns,1); 22 | sources = starfish(ts,narms,amp); 23 | sources = 3.0*sources; 24 | strengths = randn(ns,1); 25 | 26 | % targets 27 | 28 | nt = 20; 29 | ts = 0.0+2*pi*rand(nt,1); 30 | targets = starfish(ts,narms,amp); 31 | targets = targets.*repmat(rand(1,nt),2,1); 32 | 33 | % plot geo and sources 34 | 35 | xs = chnkr.r(1,:,:); xmin = min(xs(:)); xmax = max(xs(:)); 36 | ys = chnkr.r(2,:,:); ymin = min(ys(:)); ymax = max(ys(:)); 37 | 38 | hold off 39 | plot(chnkr) 40 | hold on 41 | scatter(sources(1,:),sources(2,:),'o') 42 | scatter(targets(1,:),targets(2,:),'x') 43 | axis equal 44 | 45 | zk = rand() + 1i*rand(); 46 | 47 | skern = kernel('helmholtz','s',zk); 48 | dkern = kernel('helmholtz','d',zk); 49 | 50 | rhs = skern.eval(struct("r",sources),chnkr)*strengths; 51 | sys = chunkermat(chnkr,dkern); 52 | sys = -0.5*eye(chnkr.npt)+sys; 53 | 54 | sol = sys\rhs; 55 | 56 | utrue = skern.eval(struct("r",sources),struct("r",targets))*strengths; 57 | 58 | opts = []; 59 | opts.corrections = true; 60 | cormat = chunkerkernevalmat(chnkr,dkern,targets,opts); 61 | opts = []; 62 | opts.forcesmooth = true; 63 | opts.cormat = cormat; 64 | u_eval_cor = chunkerkerneval(chnkr,dkern,sol,targets,opts); 65 | 66 | assert(norm(utrue-u_eval_cor,inf)<1e-11) 67 | opts = []; 68 | opts.forcesmooth = true; 69 | u_eval = chunkerkerneval(chnkr,dkern,sol,targets,opts); 70 | 71 | assert(norm(utrue-u_eval,inf)>1e-10) 72 | 73 | 74 | 75 | 76 | end 77 | 78 | 79 | -------------------------------------------------------------------------------- /devtools/test/chunkerkerneval_gaussidTest.m: -------------------------------------------------------------------------------- 1 | chunkerkerneval_gaussidTest0(); 2 | 3 | 4 | function chunkerkerneval_gaussidTest0() 5 | %CHUNKERKERNEVAL_GAUSSIDTEST test the routines for integrating over 6 | % chunks against Gauss' identity for the double layer potential 7 | % 8 | % 9 | 10 | seed = 8675309; 11 | rng(seed); 12 | 13 | doadap = true; 14 | 15 | % geometry parameters and construction 16 | 17 | cparams = []; 18 | cparams.eps = 1.0e-4; 19 | pref = []; 20 | pref.k = 16; 21 | narms = 5; 22 | amp = 0.5; 23 | start = tic; chnkr = chunkerfunc(@(t) starfish(t,narms,amp),cparams,pref); 24 | t1 = toc(start); 25 | 26 | 27 | % scalar function on boundary 28 | 29 | kernd = @(s,t) chnk.lap2d.kern(s,t,'d'); 30 | kerns = @(s,t) chnk.lap2d.kern(s,t,'s'); 31 | 32 | dens1 = ones(chnkr.k,chnkr.nch); 33 | 34 | nxdir = 40; 35 | 36 | rmin = min(chnkr); 37 | rmax = max(chnkr); 38 | xgrid = linspace(rmin(1),rmax(1),nxdir); 39 | ygrid = linspace(rmin(2),rmax(2),nxdir); 40 | [xx,yy] = meshgrid(xgrid,ygrid); 41 | nt = length(xx(:)); targs = zeros(2,nt); 42 | targs(1,:) = xx(:); targs(2,:) = yy(:); 43 | 44 | fprintf('computing Gauss I.D. with smooth rule...\n'); 45 | opts.forcesmooth=true; 46 | opts.accel = true; 47 | start=tic; d1 = chunkerkerneval(chnkr,kernd,dens1,targs,opts); 48 | toc(start) 49 | 50 | if doadap 51 | fprintf( ... 52 | 'computing Gauss I.D. with adaptive quadrature (may be slow)...\n'); 53 | opts.forcesmooth=false; 54 | opts.forceadap = false; 55 | opts.fac = 1.0; 56 | opts.accel = true; 57 | start=tic; d12 = chunkerkerneval(chnkr,kernd,dens1,targs,opts); 58 | toc(start) 59 | assert(all(or(abs(d12(:))<1e-6,abs(d12(:)+1)<1e-6))); 60 | dd2 = reshape(d12,size(xx)); 61 | end 62 | 63 | dd = reshape(d1,size(xx)); 64 | 65 | % 66 | 67 | figure(1) 68 | clf 69 | hold off 70 | 71 | h = pcolor(xx,yy,log10(min(abs(dd+1),abs(dd)))); set(h,'EdgeColor','none'); 72 | hold on 73 | plot(chnkr) 74 | 75 | caxis([-16,0]) 76 | 77 | colorbar 78 | 79 | if doadap 80 | figure(2) 81 | clf 82 | hold off 83 | 84 | h = pcolor(xx,yy,log10(min(abs(dd2+1),abs(dd2)))); set(h,'EdgeColor','none'); 85 | hold on 86 | plot(chnkr) 87 | 88 | caxis([-16,0]) 89 | 90 | colorbar 91 | end 92 | 93 | 94 | 95 | end 96 | 97 | 98 | -------------------------------------------------------------------------------- /devtools/test/chunkermat_quadadapTest.m: -------------------------------------------------------------------------------- 1 | chunkermat_quadadapTest0(); 2 | 3 | 4 | function chunkermat_quadadapTest0() 5 | 6 | %CHUNKERMAT_QUADADAPTEST 7 | % 8 | % define geometry and test adaptive matrix builder routine 9 | 10 | iseed = 8675309; 11 | rng(iseed); 12 | 13 | 14 | zk = randn() + 1i*randn(); 15 | 16 | cparams = []; 17 | cparams.eps = 1.0e-10; 18 | cparams.nover = 2; 19 | pref = []; 20 | pref.k = 16; 21 | narms = 3; 22 | amp = 0.25; 23 | start = tic; chnkr = chunkerfunc(@(t) starfish(t,narms,amp),cparams,pref); 24 | t1 = toc(start); 25 | 26 | fprintf('%5.2e s : time to build geo\n',t1) 27 | 28 | % sources 29 | 30 | ns = 10; 31 | ts = 0.0+2*pi*rand(ns,1); 32 | sources = starfish(ts,narms,amp); 33 | sources = 3.0*sources; 34 | strengths = randn(ns,1); 35 | 36 | % targets 37 | 38 | nt = 3; 39 | ts = 0.0+2*pi*rand(nt,1); 40 | targets = starfish(ts,narms,amp); 41 | targets = targets.*repmat(rand(1,nt),2,1); 42 | 43 | % plot geo and sources 44 | 45 | % xs = chnkr.r(1,:,:); xmin = min(xs(:)); xmax = max(xs(:)); 46 | % ys = chnkr.r(2,:,:); ymin = min(ys(:)); ymax = max(ys(:)); 47 | % 48 | % figure(1) 49 | % clf 50 | % hold off 51 | % plot(chnkr) 52 | % hold on 53 | % scatter(sources(1,:),sources(2,:),'o') 54 | % scatter(targets(1,:),targets(2,:),'x') 55 | % axis equal 56 | % 57 | % 58 | 59 | % build layer potential matrix with GGQ routine for comparison 60 | 61 | fkern = @(s,t) chnk.lap2d.kern(s,t,'S'); 62 | fkern = @(s,t) chnk.helm2d.kern(zk,s,t,'D'); 63 | 64 | start = tic; mat1 = chunkermat(chnkr,fkern); 65 | t1 = toc(start); 66 | 67 | fprintf('%5.2e s : time to assemble matrix (GGQ nbor)\n',t1) 68 | 69 | % 70 | 71 | % use adaptive routine to build matrix (self done by ggq, nbor by adaptive) 72 | 73 | type = 'log'; 74 | opts = []; opts.robust = false; 75 | opdims = [1 1]; 76 | start = tic; 77 | mat2 = chnk.quadadap.buildmat(chnkr,fkern,opdims,type,opts); 78 | t1 = toc(start); 79 | 80 | fprintf('%5.2e s : time to assemble matrix (adap nbor)\n',t1); 81 | 82 | 83 | % compare 84 | 85 | assert(norm(mat1-mat2,'fro')/norm(mat1,'fro') < 1e-9); 86 | 87 | 88 | 89 | 90 | 91 | end 92 | 93 | 94 | -------------------------------------------------------------------------------- /devtools/test/chunkrgrphOpdimTest.m: -------------------------------------------------------------------------------- 1 | chunkrgrphOpdimTest0(); 2 | 3 | 4 | function chunkrgrphOpdimTest0() 5 | 6 | verts = [-3 1; 3 1; 3 5; -3 5; 7 | -3 -5; 3 -5; 3 -1; -3 -1].'; 8 | 9 | edge2verts = [ 10 | -1, 1, 0, 0, 0, 0, 0, 0; 11 | 0, -1, 1, 0, 0, 0, 0, 0; 12 | 0, 0, -1, 1, 0, 0, 0, 0; 13 | 1, 0, 0, -1, 0, 0, 0, 0; 14 | 0, 0, 0, 0, -1, 1, 0, 0; 15 | 0, 0, 0, 0, 0, -1, 1, 0; 16 | 0, 0, 0, 0, 0, 0, -1, 1; 17 | 0, 0, 0, 0, 1, 0, 0, -1]; 18 | 19 | edge2verts = sparse(edge2verts); 20 | 21 | fchnks = {}; % this by default gives me straight lines 22 | 23 | prefs = struct('maxchunklen',0.5); 24 | [cgrph] = chunkgraph(verts, edge2verts, fchnks, prefs); 25 | 26 | % kerns 27 | 28 | zk0 = 1; % exterior 29 | zk1 = 3; % interior 30 | coef = [1 -1j*real(zk0)]; 31 | cc = [1 1; 1 1]; % these numbers might be wrong... 32 | 33 | fkern11 = @(s,t) chnk.helm2d.kern(zk0,s,t,'all',cc) - chnk.helm2d.kern(zk1,s,t,'all',cc); 34 | fkern12 = @(s,t) chnk.helm2d.kern(zk0,s,t,'c2trans',coef); 35 | fkern21 = @(s,t) chnk.helm2d.kern(zk0,s,t,'trans_rep'); 36 | fkern22 = @(s,t) chnk.helm2d.kern(zk0,s,t,'c',[1,1i]); 37 | 38 | chnk_trans_flag = [1 1 1 1 0 0 0 0]; 39 | 40 | fkerns = {}; 41 | 42 | ncurve = 8; 43 | 44 | for it=1:ncurve 45 | for is=1:ncurve 46 | kern_type = [chnk_trans_flag(it) chnk_trans_flag(is)]; 47 | if all(kern_type==[1 1]), fkerns{it,is} = fkern11; end 48 | if all(kern_type==[1 0]), fkerns{it,is} = fkern12; end 49 | if all(kern_type==[0 1]), fkerns{it,is} = fkern21; end 50 | if all(kern_type==[0 0]), fkerns{it,is} = fkern22; end 51 | end 52 | end 53 | 54 | opts = struct('nonsmoothonly',false, 'rcip',true); 55 | [sysmat] = chunkermat(cgrph, fkerns, opts); 56 | 57 | end 58 | 59 | 60 | -------------------------------------------------------------------------------- /devtools/test/flagnearTest.m: -------------------------------------------------------------------------------- 1 | flagnearTest0(); 2 | 3 | 4 | function flagnearTest0() 5 | 6 | %FLAGNEARTEST 7 | % 8 | % This file tests the flagnear routine against brute force 9 | 10 | % 11 | 12 | cparams = []; 13 | cparams.eps = 1.0e-6; 14 | pref = []; 15 | pref.k = 16; 16 | narms = 10; 17 | amp = 0.5; 18 | start = tic; chnkr = chunkerfunc(@(t) starfish(t,narms,amp),cparams,pref); 19 | t1 = toc(start); 20 | 21 | [~,~,info] = sortinfo(chnkr); 22 | assert(info.ier == 0,'adjacency issues after chunk build starfish'); 23 | 24 | 25 | fac = 0.7; 26 | 27 | nt = 1000; 28 | scal = 2*rand(1,nt); 29 | tr = 2*pi*rand(1,nt); 30 | 31 | targs = bsxfun(@times,starfish(tr,narms,amp),scal); 32 | 33 | opts = []; opts.fac = fac; 34 | start = tic; flag = flagnear(chnkr,targs,opts); t1 = toc(start); 35 | fprintf('%5.2e s : time for flagnear routine\n',t1); 36 | 37 | % brute force (almost intentionally dumb) 38 | 39 | lens = chunklen(chnkr); 40 | 41 | flag2 = sparse([],[],[],nt,chnkr.nch); 42 | for i = 1:chnkr.nch 43 | ris = chnkr.r(:,:,i); 44 | leni = lens(i); 45 | for j = 1:chnkr.k 46 | rj = ris(:,j); 47 | for l = 1:nt 48 | dist = sqrt(sum((rj-targs(:,l)).^2,1)); 49 | if dist < fac*leni 50 | flag2(l,i) = true; 51 | end 52 | end 53 | end 54 | end 55 | 56 | assert(nnz(flag2 ~= flag) == 0) 57 | 58 | 59 | 60 | 61 | end 62 | 63 | 64 | -------------------------------------------------------------------------------- /devtools/test/flagrectTest.m: -------------------------------------------------------------------------------- 1 | flagrectTest0(); 2 | 3 | 4 | function flagrectTest0() 5 | %flagrectTest 6 | % 7 | % tests the flagging routine based on rectangles 8 | % 9 | 10 | ngrid = 100; 11 | chnkr = chunkerfunc(@(t) starfish(t)); 12 | chnkr = refine(chnkr); 13 | rmin = min(chnkr); rmax = max(chnkr); 14 | dr = rmax-rmin; rmin = rmin-dr/2; rmax = rmax+dr/2; 15 | x = linspace(rmin(1),rmax(1),ngrid); 16 | y = linspace(rmin(2),rmax(2),ngrid); 17 | [xx,yy] = meshgrid(x,y); 18 | 19 | targets = [xx(:).'; yy(:).']; 20 | 21 | sp = flagnear_rectangle(chnkr,targets); 22 | sp2 = flagnear_rectangle_grid(chnkr,x,y); 23 | 24 | assert(nnz(sp-sp2) == 0); 25 | 26 | %ispec = (sp2*ones(chnkr.nch,1) > 0); 27 | 28 | %ells = ellipses(chnkr,1.8); 29 | %rects = bounding_rects(ells); 30 | 31 | 32 | %clf 33 | %plot(chnkr,'m') 34 | %hold on 35 | %scatter(targets(1,ispec),targets(2,ispec),'bo') 36 | %scatter(targets(1,~ispec),targets(2,~ispec),'go') 37 | %scatter(ells(1,:),ells(2,:),'rx') 38 | %scatter(rects(1,:),rects(2,:),'mx') 39 | 40 | 41 | 42 | 43 | 44 | end 45 | 46 | 47 | function rects = bounding_rects(convreg) 48 | % find minimal area bounding rectangle for each region 49 | 50 | [dim,m,n] = size(convreg); 51 | xreg = reshape(convreg(1,:,:),m,n); 52 | yreg = reshape(convreg(2,:,:),m,n); 53 | 54 | dx = diff([xreg; xreg(1,:)],1,1); 55 | dy = diff([yreg; yreg(1,:)],1,1); 56 | dnrm = sqrt(dx.^2+dy.^2); 57 | 58 | dx = reshape(dx./dnrm,1,m,n); 59 | dy = reshape(dy./dnrm,1,m,n); 60 | 61 | d1 = [dx;dy]; 62 | d2 = [-dy;dx]; 63 | 64 | rects = zeros(2,4,n); 65 | 66 | for i = 1:n 67 | d1i = d1(:,:,i); 68 | d2i = d2(:,:,i); 69 | pts = convreg(:,:,i).'; 70 | d1c = pts*d1i; 71 | d2c = pts*d2i; 72 | d1emax = max(d1c,[],1); 73 | d1emin = min(d1c,[],1); 74 | d1eh = d1emax-d1emin; 75 | d2emax = max(d2c,[],1); 76 | d2emin = min(d2c,[],1); 77 | d2eh = d2emax-d2emin; 78 | areas = reshape(d1eh.*d2eh,m,1); 79 | [~,j] = min(areas); 80 | 81 | d1jmax = d1emax(j); 82 | d1jmin = d1emin(j); 83 | d2jmax = d2emax(j); 84 | d2jmin = d2emin(j); 85 | 86 | d1j = d1i(:,j); 87 | d2j = d2i(:,j); 88 | 89 | rects(:,:,i) = [d1jmax*d1j+d2jmax*d2j, d1jmin*d1j+d2jmax*d2j, ... 90 | d1jmin*d1j+d2jmin*d2j, d1jmax*d1j+d2jmin*d2j]; 91 | 92 | end 93 | end -------------------------------------------------------------------------------- /devtools/test/flagselfTest.m: -------------------------------------------------------------------------------- 1 | flagselfTest0(); 2 | 3 | 4 | function flagselfTest0() 5 | % FLAGSELFTEST test the routine for flagging when sources and targets 6 | % overlap 7 | 8 | 9 | nsrc = 40000; 10 | xtarg = linspace(0,1,floor(sqrt(nsrc))); 11 | ytarg = linspace(0,2,floor(sqrt(nsrc))); 12 | [xxsrc,yysrc] = meshgrid(xtarg,ytarg); 13 | srcs = zeros(2,length(xxsrc(:))); 14 | srcs(1,:) = xxsrc(:); srcs(2,:) = yysrc(:); 15 | 16 | nsrc = size(srcs,2); 17 | 18 | 19 | targs = [srcs, [1;2].*rand(2,100)]; 20 | P = randperm(size(targs,2)); 21 | targs = targs(:,P)+1e-15*(2*rand(size(targs))-1); 22 | 23 | tic 24 | flagslf = chnk.flagself(srcs, targs); 25 | toc 26 | fprintf('number of flagged points: %d\n', size(flagslf,2)) 27 | assert(size(flagslf,2) == nsrc) 28 | 29 | 30 | errs = sum(vecnorm(srcs(:,flagslf(1,:)) - targs(:,flagslf(2,:)))>1e-10); 31 | fprintf('number of incorrectly flagged points: %d\n', errs) 32 | assert(norm(srcs(:,flagslf(1,:)) - srcs(:,P(flagslf(2,:))),1)<1e-6) 33 | 34 | end 35 | 36 | 37 | -------------------------------------------------------------------------------- /devtools/test/gradient_check.m: -------------------------------------------------------------------------------- 1 | function errs = gradient_check(fcn, x0, pert,niter,ifprint) 2 | %GRADIENT_CHECK gradient testing function 3 | % 4 | 5 | niter1 = 6; 6 | ifprint1 = true; 7 | if nargin >= 4 && ~isempty(niter) 8 | niter1 = niter; 9 | end 10 | if nargin >= 5 && ~isempty(ifprint) 11 | ifprint1 = ifprint; 12 | end 13 | 14 | eps = pert*randn(size(x0)); 15 | 16 | c = 0.1; 17 | eps = eps/(c^2); 18 | 19 | [f0, g0] = fcn(x0); 20 | x1 = zeros(size(x0)); 21 | 22 | errs = zeros(niter1,1); 23 | 24 | cfprintf(ifprint1,"Change, result\n"); 25 | for iter = 1:niter1 26 | eps = eps*c; 27 | for i = 1:length(eps) 28 | x1(i) = x0(i) + eps(i); 29 | end 30 | [f1, g1] = fcn(x1); 31 | 32 | err = 0.0; 33 | for i = 1:length(x0) 34 | err = err + (g0(i) + g1(i))*eps(i); 35 | end 36 | err = 1.0 - 0.5*err/(f1 - f0); 37 | errs(iter) = err; 38 | cfprintf(ifprint1,"|eps|: %1.5e, err %1.5e\n", ... 39 | norm(eps,'fro'), err); 40 | end 41 | end 42 | 43 | function cfprintf(ifprint,varargin) 44 | 45 | if (ifprint); fprintf(varargin{:}); end 46 | 47 | end 48 | -------------------------------------------------------------------------------- /devtools/test/helm2d_greenTest.m: -------------------------------------------------------------------------------- 1 | helm2d_greenTest0(); 2 | 3 | 4 | function helm2d_greenTest0() 5 | %HELM2D_GREENTEST 6 | % 7 | % test that gradients are set up right in chnk.helm2d.green 8 | 9 | iseed = 8675309; 10 | rng(iseed); 11 | 12 | zk = randn() + 1i*randn(); 13 | start_eps = 1.0; 14 | src = randn(2,1); trg = randn(2,1); mu = randn(2,1); 15 | srcn = randn(2,1); srcn = srcn/(norm(srcn)); 16 | 17 | fcn = @(x) fcn1(zk,src,x); 18 | fcnx = @(x) fcnx1(zk,src,x); 19 | fcny = @(x) fcny1(zk,src,x); 20 | 21 | niter = 9; 22 | errsf = gradient_check(fcn,trg,start_eps,niter); 23 | errsfx = gradient_check(fcnx,trg,start_eps,niter); 24 | errsfy = gradient_check(fcny,trg,start_eps,niter); 25 | 26 | assert(min(errsf) < 1e-10); 27 | assert(min(errsfx) < 1e-8); 28 | assert(min(errsfy) < 1e-8); 29 | 30 | 31 | 32 | end 33 | 34 | 35 | function [f,g] = fcn1(zk,src,trg) 36 | 37 | [f,g] = chnk.helm2d.green(zk,src,trg); 38 | 39 | end 40 | 41 | function [f,g] = fcnx1(zk,src,trg) 42 | 43 | [~,g1,h1] = chnk.helm2d.green(zk,src,trg); 44 | f = g1(1); 45 | g = h1(1:2); 46 | 47 | end 48 | 49 | function [f,g] = fcny1(zk,src,trg) 50 | 51 | [~,g1,h1] = chnk.helm2d.green(zk,src,trg); 52 | f = g1(2); 53 | g = h1(2:3); 54 | 55 | end 56 | -------------------------------------------------------------------------------- /devtools/test/kernelopTest.m: -------------------------------------------------------------------------------- 1 | %KERNELOPTEST verify kernel class operations are correct 2 | 3 | % setup points 4 | src = []; 5 | src.r = [[0;0],[0;1]]; 6 | src.n = randn(size(src.r)); src.n = src.n./vecnorm(src.n); 7 | 8 | targ = []; 9 | targ.r = [[1;1],[-1;0]]; 10 | targ.n = randn(size(targ.r)); targ.n = targ.n./vecnorm(targ.n); 11 | 12 | % set primitive kernels 13 | skern = kernel('lap','s'); 14 | dkern = kernel('helm','d',1); 15 | 16 | % set scalar 17 | a = pi*1i; 18 | 19 | % interleave kernels 20 | fkern1 =kernel([skern;dkern]); 21 | 22 | % multiply and divide by a 23 | fkern2 = a.*fkern1; 24 | fkern3 = fkern1/a; 25 | 26 | assert(norm(fkern2.eval(src,targ) - a*fkern1.eval(src,targ))<1e-10) 27 | assert(norm(fkern3.eval(src,targ) - 1/a*fkern1.eval(src,targ))<1e-10) 28 | 29 | % negate a kernel 30 | nkern = -skern; 31 | assert(norm(nkern.eval(src,targ) + skern.eval(src,targ))<1e-10) 32 | 33 | % add and subtract kernels 34 | ckern1 = skern + dkern; 35 | ckern2 = skern - dkern; 36 | assert(norm(ckern1.eval(src,targ) - (skern.eval(src,targ)+dkern.eval(src,targ)))<1e-10) 37 | assert(norm(ckern2.eval(src,targ) - (skern.eval(src,targ)-dkern.eval(src,targ)))<1e-10) 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /devtools/test/legeexpsunitTest.m: -------------------------------------------------------------------------------- 1 | legeexpsunitTest0(); 2 | 3 | 4 | function legeexpsunitTest0() 5 | % 6 | 7 | 8 | k = 19; 9 | 10 | [x,w,u,v] = lege.exps(k); 11 | 12 | dmat = lege.dermat(k,u,v); 13 | imat = lege.intmat(k,u,v); 14 | 15 | pv = sin(x); 16 | dpv_true = cos(x); 17 | ipv_true = -cos(x)+cos(-1); 18 | 19 | dpv = dmat*pv; 20 | ipv = imat*pv; 21 | 22 | assert(norm(dpv-dpv_true) < 1e-12) 23 | assert(norm(ipv-ipv_true) < 1e-14) 24 | 25 | cfs = randn(k,1); 26 | cfsint1 = lege.intpol(cfs); 27 | cfsintold = lege.intpol(cfs,'original'); 28 | fun = @(t) lege.exev(t,cfs); 29 | 30 | for j = 1:k 31 | itrue = integral(fun,-1,x(j)); 32 | icoefs = lege.exev(x(j),cfsint1); 33 | assert(abs(itrue-icoefs)< 1e-14); 34 | end 35 | 36 | 37 | 38 | end 39 | 40 | 41 | -------------------------------------------------------------------------------- /devtools/test/singularkernelTest.m: -------------------------------------------------------------------------------- 1 | singularkernelTest0(); 2 | 3 | 4 | function singularkernelTest0() 5 | %SINGULARKERNELTEST check that principal value and hypersingular type 6 | % quadratures are working. 7 | % 8 | 9 | seed = 8675309; 10 | rng(seed); 11 | 12 | doadap = false; 13 | 14 | % geometry parameters and construction 15 | 16 | cparams = []; 17 | cparams.eps = 1.0e-9; 18 | pref = []; 19 | pref.k = 16; 20 | narms = 5; 21 | amp = 0.3; 22 | start = tic; chnkr = chunkerfunc(@(t) starfish(t,narms,amp),cparams,pref); 23 | t1 = toc(start); 24 | 25 | % sources 26 | 27 | ns = 10; 28 | ts = 0.0+2*pi*rand(ns,1); 29 | sources = starfish(ts,narms,amp); 30 | sources = 3.0*sources; 31 | strengths = randn(ns,1); 32 | 33 | hold off 34 | plot(chnkr) 35 | hold on 36 | scatter(sources(1,:),sources(2,:),'o') 37 | axis equal 38 | 39 | % 40 | 41 | % kernel defs 42 | 43 | kernd = kernel('lap','d'); 44 | kerns = kernel('lap','s'); 45 | kerndprime = kernel('lap','dprime'); 46 | kernsprime = kernel('lap','sprime'); 47 | kernstau = kernel('lap','stau'); 48 | 49 | 50 | % eval u and dudn on boundary 51 | 52 | srcinfo = []; srcinfo.r = sources; 53 | 54 | eps = 1e-15; 55 | [ubdry,gradubdry] = kerns.fmm(eps,srcinfo,chnkr.r(:,:),strengths); 56 | unbdry = sum(chnkr.n(:,:).*gradubdry,1); 57 | tau = -chnk.perp(chnkr.n(:,:)); 58 | utbdry = sum(tau(:,:).*gradubdry,1); 59 | 60 | wtsc = chnkr.wts; 61 | sprimemat = chunkermat(chnkr,kernsprime); 62 | staumat = chunkermat(chnkr,kernstau); 63 | sys = 0.5*eye(chnkr.npt) + sprimemat + ones(chnkr.npt,1)*(wtsc(:).'); 64 | mu = sys\unbdry(:); 65 | utau = staumat*mu; 66 | 67 | relerr = norm(utau-utbdry(:))/norm(utbdry); 68 | fprintf('%5.2e : error in utau test (testing pv integration)\n',relerr); 69 | assert(relerr < 1e-9); 70 | 71 | dmat = chunkermat(chnkr,kernd); 72 | dprimemat = chunkermat(chnkr,kerndprime); 73 | sys = -0.5*eye(chnkr.npt) + dmat; 74 | mu = sys\ubdry(:); 75 | un = dprimemat*mu; 76 | 77 | relerr = norm(un-unbdry(:))/norm(unbdry); 78 | fprintf('%5.2e : error in un test (testing hs integration)\n',relerr); 79 | 80 | 81 | end 82 | 83 | 84 | -------------------------------------------------------------------------------- /devtools/test/slicegraphTest.m: -------------------------------------------------------------------------------- 1 | slicegraphTest0(); 2 | 3 | function slicegraphTest0() 4 | % create a geometry of concentric squares 5 | 6 | % outer square 7 | verts_out = [[1;1],[1;-1],[-1;-1],[-1;1]]; 8 | 9 | % inner square 10 | verts_in = verts_out/2; 11 | 12 | verts = [verts_out, verts_in]; 13 | 14 | % geometry will be a series of loops through subsets of vertices 15 | id_vert_out = 1:4; 16 | % call helper function 17 | e2v_out = [id_vert_out;circshift(id_vert_out,1)]; 18 | 19 | id_vert_in = 5:8; 20 | e2v_in = [id_vert_in;circshift(id_vert_in,1)]; 21 | 22 | % combine lists of edges and build chunkgraph 23 | edge_2_verts = [e2v_out,e2v_in]; 24 | cgrph = chunkgraph(verts,edge_2_verts); 25 | 26 | % slice chunkgraph and test points assigned correctly 27 | ichs = [1,5:8]; 28 | cgrph_slc = slicegraph(cgrph, ichs); 29 | assert(norm(cgrph_slc.r(:) - merge(cgrph.echnks(ichs)).r(:)) < 1e-14) 30 | 31 | figure(1); 32 | clf; 33 | plot_regions(cgrph_slc) 34 | axis equal 35 | 36 | 37 | % build a test system matrix 38 | dkern = -2*kernel('lap','d'); 39 | sysmat = chunkermat(cgrph, dkern); 40 | 41 | % build system matrix on sliced problem 42 | ichs = 5:8; 43 | cgrph_slc = slicegraph(cgrph, ichs); 44 | 45 | sysmat_slc = chunkermat(cgrph_slc, dkern); 46 | 47 | % check that sliced matrix is correct 48 | idslce = (cgrph.npt - cgrph_slc.npt) + (1:cgrph_slc.npt); 49 | 50 | matdiff = norm(sysmat_slc - sysmat(idslce, idslce)); 51 | fprintf('error in sliced system matrix is %e\n',matdiff) 52 | assert(matdiff < 1e-10) 53 | end -------------------------------------------------------------------------------- /devtools/test/smootherTest.m: -------------------------------------------------------------------------------- 1 | nv = 3; 2 | z = exp(1j*2*pi*(1:nv)/nv); 3 | verts = [real(z); imag(z)]; 4 | 5 | opts = []; 6 | opts.lam = 10; 7 | [chnkr,err,err_by_pt] = chnk.smoother.smooth(verts,opts); 8 | 9 | assert(err<1E-6) 10 | -------------------------------------------------------------------------------- /devtools/test/stokes_dtracTest.m: -------------------------------------------------------------------------------- 1 | stokes_dtracTest0(); 2 | 3 | 4 | function stokes_dtracTest0() 5 | srcinfo = []; 6 | srcinfo.r = rand(2,1); 7 | srcinfo.n = rand(2,1); 8 | 9 | targinfo = []; 10 | targinfo.r = rand(2,1); 11 | targinfo.n = rand(2,1); 12 | 13 | strengths = rand(2,1); 14 | 15 | mu = 1.1; 16 | 17 | kernt = kernel('stok', 'dtrac', mu); 18 | kerng = kernel('stok', 'dgrad', mu); 19 | kernp = kernel('stok', 'dpres', mu); 20 | 21 | Kt = kernt.eval(srcinfo, targinfo)*strengths; 22 | Kg = kerng.eval(srcinfo, targinfo)*strengths; 23 | Kp = kernp.eval(srcinfo, targinfo)*strengths; 24 | 25 | du = reshape(Kg, [2,2,1]); 26 | dut = permute(du, [2,1,3]); 27 | eu = du + dut; 28 | 29 | euxx = squeeze(eu(1,1,:)); 30 | euxy = squeeze(eu(1,2,:)); 31 | euyy = squeeze(eu(2,2,:)); 32 | f = zeros(2,1); 33 | p = Kp.'; 34 | ntx = targinfo.n(1,:).'; 35 | nty = targinfo.n(2,:).'; 36 | f(1:2:end) = -p.*ntx + (euxx.*ntx + euxy.*nty)*mu; 37 | f(2:2:end) = -p.*nty + (euxy.*ntx + euyy.*nty)*mu; 38 | 39 | norm(f - Kt) 40 | 41 | 42 | end 43 | 44 | 45 | -------------------------------------------------------------------------------- /docs/_static/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/docs/_static/.keep -------------------------------------------------------------------------------- /docs/_templates/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/docs/_templates/.keep -------------------------------------------------------------------------------- /docs/assets/images/scatter_star_trim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastalgorithms/chunkie/b3e4677da30198ad1ed0886f0e489922251fb5d7/docs/assets/images/scatter_star_trim.png -------------------------------------------------------------------------------- /docs/gallery.rst: -------------------------------------------------------------------------------- 1 | Gallery 2 | ========== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Contents: 7 | -------------------------------------------------------------------------------- /docs/guide.rst: -------------------------------------------------------------------------------- 1 | chunkIE User Guide 2 | =================== 3 | 4 | Apologies that this guide is still under construction. There 5 | are examples for the most common uses. 6 | 7 | Some `tutorial worksheets `_ are available. 8 | 9 | 10 | Detailed documentation of all high-level functions and 11 | classes can be obtained by viewing the source file or by 12 | typing "help [function name]" in a MATLAB command window: 13 | 14 | .. code:: matlab 15 | 16 | help chunker 17 | 18 | 19 | 20 | .. toctree:: 21 | :maxdepth: 1 22 | :caption: Contents: 23 | 24 | guide/chunkers 25 | guide/kerns 26 | guide/simplebvps 27 | guide/largerproblems 28 | guide/chunkgraphs 29 | guide/chunkgraphbvps 30 | guide/transmission 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/guide/largerproblems.rst: -------------------------------------------------------------------------------- 1 | 2 | Larger Boundary Value Problems 3 | ================================ 4 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx_rtd_theme 2 | sphinx-math-dollar 3 | --------------------------------------------------------------------------------