<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://e6.ijs.si/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Uduh</id>
		<title>Medusa: Coordinate Free Mehless Method implementation - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://e6.ijs.si/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Uduh"/>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Special:Contributions/Uduh"/>
		<updated>2026-06-28T00:09:24Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.1</generator>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3535</id>
		<title>Medusa</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3535"/>
				<updated>2022-12-07T18:28:21Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--__NOTITLE__--&amp;gt;&lt;br /&gt;
'''Welcome to the Medusa wiki. To visit the main website, go to [http://e6.ijs.si/medusa/ http://e6.ijs.si/medusa/].'''&lt;br /&gt;
&lt;br /&gt;
In [http://e6.ijs.si/ParallelAndDistributedSystems/ Parallel and Distributed Systems Laboratory] we are working on a C++ library that is first and foremost focused on tools for solving Partial Differential Equations by meshless methods. The basic idea is to create generic codes for tools that are needed for solving not only PDEs but many other problems, e.g. Moving Least Squares approximation, $k$-d tree, domain generation engines, etc.&lt;br /&gt;
We call this open source meshless project [http://e6.ijs.si/medusa/ Medusa: Coordinate Free Meshless Method implementation (MM)].&lt;br /&gt;
&lt;br /&gt;
Technical details about code and examples  can be found on our [http://e6.ijs.si/medusa/docs/ documentation page] and [https://gitlab.com/e62Lab/medusa Gitlab repository]. [[File:C.png|100px||link=https://gitlab.com/e62Lab/medusa|alt=Alt text|code]] [[File:doxygen.png|100px|link=http://e6.ijs.si/medusa/docs/|alt=Alt text|Documentation page]]&lt;br /&gt;
&lt;br /&gt;
This wiki site is meant for more relaxed discussions about general principles, possible and already implemented applications, preliminary analyses, etc.&lt;br /&gt;
Note, that there are many grammatical mistakes, typos, stupid sentences, etc. This wiki is meant for quick information exchange and therefore we do not invest a lot of energy into styling :).  &lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
* [https://gitlab.com/e62Lab/medusa Code on Gitlab]&lt;br /&gt;
* [[How to build | Installation and building]]&lt;br /&gt;
* [[Including this library in your project | Including this library in your project]]&lt;br /&gt;
* [[Testing | Running tests]]&lt;br /&gt;
* [http://e6.ijs.si/medusa/docs/ Technical documentation]&lt;br /&gt;
* [[Coding style | Coding style]]&lt;br /&gt;
* [[Wiki editing guide | Wiki editing and backup guide]]&lt;br /&gt;
&lt;br /&gt;
== Building blocks ==&lt;br /&gt;
Medusa is modular coordinate-free parallel implementation of a numerical framework designed, but not limited to, for solving PDEs. In this section we present main modules of the library that can be also used as a standalone tools. &lt;br /&gt;
* [[Positioning of computational nodes]] &lt;br /&gt;
* [[Relaxation of the nodal distribution]]&lt;br /&gt;
* [[Refinement of the nodal distribution]]&lt;br /&gt;
* [[k-d tree|''k''-d tree and other spatial search structures]] &lt;br /&gt;
* [[Solving system | Solving linear system - including over and underdetermined systems]]&lt;br /&gt;
* [[Weighted Least Squares (WLS)]]&lt;br /&gt;
* [[Computation of shape functions]]&lt;br /&gt;
* [[Radial basis function-generated finite differences (RBF-FD)]]&lt;br /&gt;
* [[Ghost nodes (theory)]]&lt;br /&gt;
* [[Integrators for time stepping]]&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
In this section we present exact examples. Each of the below solutions can be found also in in the repository under examples. More explanation about the physical background and solution procedure can be found in following sections.&lt;br /&gt;
* [[Philosophy of examples and how to run them]]&lt;br /&gt;
* [[Poisson's equation]]&lt;br /&gt;
* [[Heat equation]]&lt;br /&gt;
* [[Linear elasticity]]&lt;br /&gt;
* [[Complex-valued problems]]&lt;br /&gt;
* [[Coupled domains]]&lt;br /&gt;
* [[Parametric domains | Parametric domains &amp;amp;ndash; Curved surface with variable density]]&lt;br /&gt;
* [[NURBS domains | Domains modeled with non-uniform rational basis splines (NURBS)]]&lt;br /&gt;
* [[Determining the interior of the domain by oversampling the boundary]]&lt;br /&gt;
* [[Computer-aided design - Importing IGES and STEP files]]&lt;br /&gt;
* [[Realistic 3D models|Working with 3D surface mesh models ]]&lt;br /&gt;
* [[customization | Operator customization]]&lt;br /&gt;
* [[Ghost nodes]]&lt;br /&gt;
* [[Electromagnetic scattering]]&lt;br /&gt;
* [[Schrödinger equation]]&lt;br /&gt;
* [[Wave equation]]&lt;br /&gt;
* [[Cahn-Hilliard equation]]&lt;br /&gt;
* [[Fluid mechanics]]&lt;br /&gt;
* [[Solid Mechanics | Solid mechanics]]&lt;br /&gt;
&lt;br /&gt;
== Discussions / Applications ==&lt;br /&gt;
This section is meant for general discussion about the physical background of the examples, the solution procedures, various applications, etc. Note, that code snippets presented in discussion might not reflect the actual state of Medusa.  &lt;br /&gt;
* [[Convection Diffusion equation | Convection Diffusion equation]]&lt;br /&gt;
* [[Adaptivity|H-adaptivity]]&lt;br /&gt;
* [[Hp-adaptivity]]&lt;br /&gt;
* [[Solid Mechanics]]&lt;br /&gt;
** [[Point contact]]&lt;br /&gt;
** [[Hertzian contact]]&lt;br /&gt;
** [[Cantilever beam]]&lt;br /&gt;
** [[Fretting fatigue case]]&lt;br /&gt;
** [[Plasticity]]&lt;br /&gt;
* [[Fluid Mechanics]]&lt;br /&gt;
** [[Lid driven cavity]]&lt;br /&gt;
** [[de Vahl Davis natural convection test]]&lt;br /&gt;
** [[Natural convection in 3D irregular domain]]&lt;br /&gt;
** [[Natural convection from heated cylinder]]&lt;br /&gt;
** [[Natural convection between concentric cylinders]]&lt;br /&gt;
** [[Non-Newtonian fluid]]&lt;br /&gt;
* [[Computational electromagnetics]]&lt;br /&gt;
** [[Triple dielectric step in 1D]]&lt;br /&gt;
** [[Scattering from an infinite cylinder]]&lt;br /&gt;
** [[Point source near an anisotropic lens]]&lt;br /&gt;
* Other applications&lt;br /&gt;
** [[Attenuation due to liquid water content in the atmosphere|Attenuation of a satellite communication]]&lt;br /&gt;
** [[Heart rate variability detection]]&lt;br /&gt;
** [[Bioheat equation]]&lt;br /&gt;
&lt;br /&gt;
== Performance analyses ==&lt;br /&gt;
* [[Execution on Intel® Xeon Phi™ co-processor]]&lt;br /&gt;
* [[1D MLSM and FDM comparison]]&lt;br /&gt;
* [[:File:tech_report.pdf|Execution overheads due to clumsy types::technical report]] [[File:pdf-file.gif]]&lt;br /&gt;
* [[Solving sparse systems]]&lt;br /&gt;
* [[Eigen paralelization]]&lt;br /&gt;
&lt;br /&gt;
== Last changes ==&lt;br /&gt;
&amp;lt;news unique=1 limit = 5&amp;gt;&lt;br /&gt;
*{{{timeanddate}}} :: {{{title}}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/news&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous ==&lt;br /&gt;
* FAQ  - [[Frequently asked questions]]. &lt;br /&gt;
* [[List of wiki contributors]]&lt;br /&gt;
* List of library contributors: [http://e6.ijs.si/medusa/about#about-contributors See the official website]&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
For all related papers including conference contributions, monographs and book chapters check https://e6.ijs.si/ParallelAndDistributedSystems/publications/&lt;br /&gt;
&lt;br /&gt;
{{Box-round|title= Selected papers |&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/98533123.pdf M. Depolli, J. Slak, G. Kosec; Parallel domain discretization algorithm for RBF-FD and other meshless numerical methods for solving PDEs, Computers &amp;amp; Structures, 2022 [DOI: 10.1016/j.compstruc.2022.106773]]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/69777155.pdf J. Slak, G. Kosec; Medusa : A C++ library for solving PDEs using strong form mesh-free methods, ACM transactions on mathematical software, vol. 47, 2021 [DOI: 10.1145/3450966]]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/56730115.pdf U. Duh, G. Kosec, J. Slak; Fast variable density node generation on parametric surfaces with application to mesh-free methods, SIAM journal on scientific computing, vol. 43, 2021 [DOI: 10.1137/20M1325642]]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/52715011.pdf M. Jančič, J. Slak, G. Kosec; Monomial augmentation guidelines for RBF-FD from accuracy versus computational time perspective, Journal of scientific computing, vol. 87, 2021 [DOI: 10.1007/s10915-020-01401-y]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/32782887.pdf J. Slak, G. Kosec; On generation of node distributions for meshless PDE discretizations, SIAM journal on scientific computing, vol. 41, 2019 [DOI: 10.1137/18M1231456]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/32424999.pdf G. Kosec, J. Slak, M. Depolli, R. Trobec, K. Pereira, S. Tomar, T. Jacquemin, S. Bordas, M. Wahab; Weak and strong from meshless methods for linear elastic problem under fretting contact conditions, Tribology international, vol. 138, 2019]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/32230439.pdf J. Slak, G. Kosec; Adaptive radial basis function-generated finite differences method for contact problems, International journal for numerical methods in engineering, vol. 119, 2019 [DOI: 10.1002/nme.6067]]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/32388135.pdf M. Maksić, V. Djurica, A. Souvent, J. Slak, M. Depolli, G. Kosec; Cooling of overhead power lines due to the natural convection, International journal of electrical power &amp;amp; energy systems, 2019]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/31107623.pdf J. Slak, G. Kosec; Refined meshless local strong form solution of Cauchy-Navier equation on an irregular domain, Engineering analysis with boundary elements, vol. 100, 2019]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/29639719.pdf M. Depolli, G. Kosec; Assessment of differential evolution for multi-objective optimization in a natural convection problem solved by a local meshless method, Engineering optimization, 2017, vol. 49, no. 4, pp. 675-692]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/29512743.pdf G. Kosec; A local numerical solution of a fluid-flow problem on an irregular domain, Advances in engineering software, vol. 120, 2018 [DOI: 10.1016/j.advengsoft.2016.05.010]]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/27912487.pdf G. Kosec, R. Trobec; Simulation of semiconductor devices with a local numerical approach, Engineering analysis with boundary elements, 2015 [DOI: 10.1016/j.enganabound.2014.07.013]]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/3218939.pdf G. Kosec, B. Šarler; Simulation of macrosegregation with mesosegregates in binary metallic casts by a meshless method, Engineering analysis with boundary elements]&lt;br /&gt;
&lt;br /&gt;
[http://comms.ijs.si/~gkosec/data/papers/27339815.pdf G. Kosec, M. Depolli, A. Rashkovska, R. Trobec; Super linear speedup in a local parallel meshless solution of thermo-fluid problem, Computers &amp;amp; Structures, vol. 133, 2014]&lt;br /&gt;
&lt;br /&gt;
[http://comms.ijs.si/~gkosec/data/papers/26785063.pdf G. Kosec, P. Zinterhof; Local strong form meshless method on multiple Graphics Processing Units, Computer modeling in engineering &amp;amp; sciences, vol. 91, 2013]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/2599419.pdf G. Kosec, B. Šarler; Solution of a low Prandtl number natural convection benchmark by a local meshless method, International journal of numerical methods for heat &amp;amp; fluid flow]&lt;br /&gt;
&lt;br /&gt;
[http://comms.ijs.si/~gkosec/data/papers/EABE2499.pdf R. Trobec, G. Kosec, M. Šterk, B. Šarler; Comparison of local weak and strong form meshless methods for 2-D diffusion equation, Engineering analysis with boundary elements, vol. 36, 2012]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/1905659.pdf G. Kosec, M. Založnik, B. Šarler, H. Combeau; A meshless approach towards solution of macrosegregation phenomena, Computers, materials &amp;amp; continua : CMC, vol. 22, 2011 ]&lt;br /&gt;
&lt;br /&gt;
[https://e6.ijs.si/ParallelAndDistributedSystems/publications/992507.pdf G. Kosec, B. Šarler; Solution of thermo-fluid problems by collocation with local pressure correction, International journal of numerical methods for heat &amp;amp; fluid flow, vol.18, 2008]&lt;br /&gt;
&lt;br /&gt;
R. Trobec, G. Kosec; Parallel scientific computing : theory, algorithms, and applications of mesh based and meshless methods, 2015&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Related pages==&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/products/medusa/&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Determining_the_interior_of_the_domain_by_oversampling_the_boundary&amp;diff=3214</id>
		<title>Determining the interior of the domain by oversampling the boundary</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Determining_the_interior_of_the_domain_by_oversampling_the_boundary&amp;diff=3214"/>
				<updated>2022-07-11T13:08:19Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Go back to [[Medusa#Examples|Examples]].&lt;br /&gt;
&lt;br /&gt;
Sometimes, the interior of a complex domain cannot be correctly determined from the discretized boundary, leading to points &amp;quot;leaking&amp;quot; out of the domain. This can for example happen with the duck model shown in [[NURBS domains]] if it is sampled with small node density (big spacing $h$).&lt;br /&gt;
&lt;br /&gt;
[[File:leaking_domain.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The easiest way to deal with this problem is to sample the boundary with a higher node density (smaller spacing $h$) and use this oversampled discretization when querying for the interior of the domain. This usage is supported by &amp;lt;code&amp;gt;GeneralFill&amp;lt;/code&amp;gt; (see [[Positioning of computational nodes]]) and can be implemented by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Oversample the domain.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; oversampled_domain = shape.discretizeBoundaryWithStep(h / 5);&lt;br /&gt;
&lt;br /&gt;
// Construct the contains function.&lt;br /&gt;
KDTree&amp;lt;Vec2d&amp;gt; contains_tree;&lt;br /&gt;
oversampled_domain.makeDiscreteContainsStructure(contains_tree);&lt;br /&gt;
auto contains_function = [&amp;amp;] (const Vec2d p) {&lt;br /&gt;
    return oversampled_domain.discreteContains(p, contains_tree);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Fill the boundary normally.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; domain = shape.discretizeBoundaryWithStep(h);&lt;br /&gt;
&lt;br /&gt;
// Fill the interior with the contains function.&lt;br /&gt;
KDTreeMutable&amp;lt;Vec2d&amp;gt; tree;&lt;br /&gt;
GeneralFill&amp;lt;Vec2d&amp;gt; gf;&lt;br /&gt;
gf(domain, h, tree, contains_function);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we have decreased the spacing by 5 in the oversampled domain. For higher node densities, less oversampling also works. The above procedure results in&lt;br /&gt;
&lt;br /&gt;
[[File:oversampled_domain.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The whole example can be found as [https://gitlab.com/e62Lab/medusa/-/blob/dev/examples/inside_by_oversampling/inside_by_oversampling.cpp inside_by_oversampling.cpp] along with the plot script that can be run by Matlab or Octave [https://gitlab.com/e62Lab/medusa/-/blob/dev/examples/inside_by_oversampling/inside_by_oversampling.m inside_by_oversampling.m].&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Computer-aided_design_-_Importing_IGES_and_STEP_files&amp;diff=3213</id>
		<title>Computer-aided design - Importing IGES and STEP files</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Computer-aided_design_-_Importing_IGES_and_STEP_files&amp;diff=3213"/>
				<updated>2022-07-05T10:26:00Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Go back to [[Medusa#Examples|Examples]].&lt;br /&gt;
&lt;br /&gt;
STEP and IGES files can be directly translated into Medusa's &amp;lt;code&amp;gt;NURBSShape&amp;lt;/code&amp;gt; '''if they only contain NURBS objects'''. Helper functions, which do that, are provided in the [https://gitlab.com/e62Lab/medusa-extras/-/tree/main/CADFilesImport Medusa-Extras repository]. For their usage, [https://dev.opencascade.org/doc/overview/html/ OpenCASCADE] library must be installed on the system.&lt;br /&gt;
&lt;br /&gt;
Some example CAD models are also provided in the repository, code that discretizes a tiger model using the strategy described in [[Determining the interior of the domain by oversampling the boundary]] is shown below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
NURBSShape&amp;lt;Vec3d, Vec2d&amp;gt; shape = translate_STEP(&amp;quot;examples/tiger.step&amp;quot;);&lt;br /&gt;
double h = 2;&lt;br /&gt;
&lt;br /&gt;
// Oversample the domain.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec3d&amp;gt; oversampled_domain = shape.discretizeBoundaryWithStep(h / 5);&lt;br /&gt;
&lt;br /&gt;
for (int i = 0; i &amp;lt; oversampled_domain.size(); i++) {&lt;br /&gt;
    oversampled_domain.normal(i) *= -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Construct the contains function.&lt;br /&gt;
KDTree&amp;lt;Vec3d&amp;gt; contains_tree;&lt;br /&gt;
oversampled_domain.makeDiscreteContainsStructure(contains_tree);&lt;br /&gt;
auto contains_function = [&amp;amp;] (const Vec3d p) {&lt;br /&gt;
    return oversampled_domain.discreteContains(p, contains_tree);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Fill the boundary normally.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec3d&amp;gt; domain = shape.discretizeBoundaryWithStep(h);&lt;br /&gt;
&lt;br /&gt;
// Fill the interior with the contains function.&lt;br /&gt;
KDTreeMutable&amp;lt;Vec3d&amp;gt; tree;&lt;br /&gt;
GeneralFill&amp;lt;Vec3d&amp;gt; gf;&lt;br /&gt;
gf(domain, h, tree, contains_function);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using the provided plot script, we get&lt;br /&gt;
&lt;br /&gt;
[[File:tiger.png|400px]]&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Computer-aided_design_-_Importing_IGES_and_STEP_files&amp;diff=3212</id>
		<title>Computer-aided design - Importing IGES and STEP files</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Computer-aided_design_-_Importing_IGES_and_STEP_files&amp;diff=3212"/>
				<updated>2022-07-04T15:18:34Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: Created page with &amp;quot;Go back to Examples.  STEP and IGES files can be directly translated into Medusa's &amp;lt;code&amp;gt;NURBSShape&amp;lt;/code&amp;gt; '''if they only contain NURBS objects'''. Helper...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Go back to [[Medusa#Examples|Examples]].&lt;br /&gt;
&lt;br /&gt;
STEP and IGES files can be directly translated into Medusa's &amp;lt;code&amp;gt;NURBSShape&amp;lt;/code&amp;gt; '''if they only contain NURBS objects'''. Helper functions, which do that, are provided in the [https://gitlab.com/e62Lab/medusa-extras/-/tree/main/ Medusa-Extras repository]. For their usage, [https://dev.opencascade.org/doc/overview/html/ OpenCASCADE] library must be installed on the system.&lt;br /&gt;
&lt;br /&gt;
Some example CAD models are also provided in the repository, code that discretizes a tiger model using the strategy described in [[Determining the interior of the domain by oversampling the boundary]] is shown below&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
NURBSShape&amp;lt;Vec3d, Vec2d&amp;gt; shape = translate_STEP(&amp;quot;examples/tiger.step&amp;quot;);&lt;br /&gt;
double h = 2;&lt;br /&gt;
&lt;br /&gt;
// Oversample the domain.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec3d&amp;gt; oversampled_domain = shape.discretizeBoundaryWithStep(h / 5);&lt;br /&gt;
&lt;br /&gt;
for (int i = 0; i &amp;lt; oversampled_domain.size(); i++) {&lt;br /&gt;
    oversampled_domain.normal(i) *= -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Construct the contains function.&lt;br /&gt;
KDTree&amp;lt;Vec3d&amp;gt; contains_tree;&lt;br /&gt;
oversampled_domain.makeDiscreteContainsStructure(contains_tree);&lt;br /&gt;
auto contains_function = [&amp;amp;] (const Vec3d p) {&lt;br /&gt;
    return oversampled_domain.discreteContains(p, contains_tree);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Fill the boundary normally.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec3d&amp;gt; domain = shape.discretizeBoundaryWithStep(h);&lt;br /&gt;
&lt;br /&gt;
// Fill the interior with the contains function.&lt;br /&gt;
KDTreeMutable&amp;lt;Vec3d&amp;gt; tree;&lt;br /&gt;
GeneralFill&amp;lt;Vec3d&amp;gt; gf;&lt;br /&gt;
gf(domain, h, tree, contains_function);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using the provided plot script, we get&lt;br /&gt;
&lt;br /&gt;
[[File:tiger.png|400px]]&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Tiger.png&amp;diff=3211</id>
		<title>File:Tiger.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Tiger.png&amp;diff=3211"/>
				<updated>2022-07-04T15:16:56Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: Uduh uploaded a new version of File:Tiger.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Tiger.png&amp;diff=3210</id>
		<title>File:Tiger.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Tiger.png&amp;diff=3210"/>
				<updated>2022-07-04T15:14:14Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3209</id>
		<title>Medusa</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3209"/>
				<updated>2022-07-04T15:05:53Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--__NOTITLE__--&amp;gt;&lt;br /&gt;
'''Welcome to the Medusa wiki. To visit the main website, go to [http://e6.ijs.si/medusa/ http://e6.ijs.si/medusa/].'''&lt;br /&gt;
&lt;br /&gt;
In [http://e6.ijs.si/ParallelAndDistributedSystems/ Parallel and Distributed Systems Laboratory] we are working on a C++ library that is first and foremost focused on tools for solving Partial Differential Equations by meshless methods. The basic idea is to create generic codes for tools that are needed for solving not only PDEs but many other problems, e.g. Moving Least Squares approximation, $k$-d tree, domain generation engines, etc.&lt;br /&gt;
We call this open source meshless project [http://e6.ijs.si/medusa/ Medusa: Coordinate Free Meshless Method implementation (MM)].&lt;br /&gt;
&lt;br /&gt;
Technical details about code and examples  can be found on our [http://e6.ijs.si/medusa/docs/ documentation page] and [https://gitlab.com/e62Lab/medusa Gitlab repository]. [[File:C.png|100px||link=https://gitlab.com/e62Lab/medusa|alt=Alt text|code]] [[File:doxygen.png|100px|link=http://e6.ijs.si/medusa/docs/|alt=Alt text|Documentation page]]&lt;br /&gt;
&lt;br /&gt;
This wiki site is meant for more relaxed discussions about general principles, possible and already implemented applications, preliminary analyses, etc.&lt;br /&gt;
Note, that there are many grammatical mistakes, typos, stupid sentences, etc. This wiki is meant for quick information exchange and therefore we do not invest a lot of energy into styling :).  &lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
* [https://gitlab.com/e62Lab/medusa Code on Gitlab]&lt;br /&gt;
* [[How to build | Installation and building]]&lt;br /&gt;
* [[Including this library in your project | Including this library in your project]]&lt;br /&gt;
* [[Testing | Running tests]]&lt;br /&gt;
* [http://e6.ijs.si/medusa/docs/ Technical documentation]&lt;br /&gt;
* [[Coding style | Coding style]]&lt;br /&gt;
* [[Wiki editing guide | Wiki editing and backup guide]]&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
In this section we present exact examples. Each of the below solutions can be found also in in the repository under examples. More explanation about the physical background and solution procedure can be found in following sections.&lt;br /&gt;
* [[Philosophy of examples and how to run them]]&lt;br /&gt;
* [[Poisson's equation]]&lt;br /&gt;
* [[Heat equation]]&lt;br /&gt;
* [[Linear elasticity]]&lt;br /&gt;
* [[Complex-valued problems]]&lt;br /&gt;
* [[Coupled domains]]&lt;br /&gt;
* [[Parametric domains | Parametric domains &amp;amp;ndash; Curved surface with variable density]]&lt;br /&gt;
* [[NURBS domains | Domains modeled with non-uniform rational basis spline's (NURBS)]]&lt;br /&gt;
* [[Determining the interior of the domain by oversampling the boundary]]&lt;br /&gt;
* [[Computer-aided design - Importing IGES and STEP files]]&lt;br /&gt;
* [[Realistic 3D models]]&lt;br /&gt;
* [[Customization]]&lt;br /&gt;
* [[Ghost nodes]]&lt;br /&gt;
* [[Electromagnetic scattering]]&lt;br /&gt;
* [[Schrödinger equation]]&lt;br /&gt;
* [[Wave equation]]&lt;br /&gt;
* [[Cahn-Hilliard equation]]&lt;br /&gt;
* [[Non-Newtonian_fluid_example | Non-Newtonian fluid]]&lt;br /&gt;
* [[Meshless Lattice Boltzmann method]]&lt;br /&gt;
&lt;br /&gt;
== Building blocks ==&lt;br /&gt;
Medusa is modular coordinate-free parallel implementation of a numerical framework designed, but not limited to, for solving PDEs. In this section we present main modules of the library that can be also used as a standalone tools. &lt;br /&gt;
* [[Positioning of computational nodes]] &lt;br /&gt;
* [[Relaxation of the nodal distribution]]&lt;br /&gt;
* [[Refinement of the nodal distribution]]&lt;br /&gt;
* [[k-d tree|''k''-d tree]] and other spatial search structures&lt;br /&gt;
* Solving [[Solving linear systems | linear systems]], [[Solving overdetermined systems | overdetermined]] and [[Solving underdetermined systems | underdetermined]]&lt;br /&gt;
* [[Weighted Least Squares (WLS)]]&lt;br /&gt;
* [[Computation of shape functions]]&lt;br /&gt;
* [[Meshless Local Strong Form Method (MLSM)]]&lt;br /&gt;
* [[Radial basis function-generated finite differences (RBF-FD)]]&lt;br /&gt;
* [[Ghost nodes (theory)]]&lt;br /&gt;
* [[Integrators for time stepping]]&lt;br /&gt;
* [[RBF Interpolation]]&lt;br /&gt;
&lt;br /&gt;
== Discussions / Applications ==&lt;br /&gt;
This section is meant for general discussion about the physical background of the examples, the solution procedures, various applications, etc. Note, that code snippets presented in discussion might not reflect the actual state of Medusa.  &lt;br /&gt;
* [[Convection Diffusion equation | Convection Diffusion equation]]&lt;br /&gt;
* [[Adaptivity]]&lt;br /&gt;
* [[Solid Mechanics]]&lt;br /&gt;
** [[Point contact]]&lt;br /&gt;
** [[Hertzian contact]]&lt;br /&gt;
** [[Cantilever beam]]&lt;br /&gt;
** [[Fretting fatigue case]]&lt;br /&gt;
** [[Plasticity]]&lt;br /&gt;
* [[Fluid Mechanics]]&lt;br /&gt;
** [[Lid driven cavity]]&lt;br /&gt;
** [[de Vahl Davis natural convection test]]&lt;br /&gt;
** [[Natural convection in 3D irregular domain]]&lt;br /&gt;
** [[Natural convection from heated cylinder]]&lt;br /&gt;
** [[Natural convection between concentric cylinders]]&lt;br /&gt;
** [[Non-Newtonian fluid]]&lt;br /&gt;
* [[Computational electromagnetics]]&lt;br /&gt;
** [[Triple dielectric step in 1D]]&lt;br /&gt;
** [[Scattering from an infinite cylinder]]&lt;br /&gt;
** [[Point source near an anisotropic lens]]&lt;br /&gt;
* Other applications&lt;br /&gt;
** [[Attenuation due to liquid water content in the atmosphere|Attenuation of a satellite communication]]&lt;br /&gt;
** [[Heart rate variability detection]]&lt;br /&gt;
** [[Bioheat equation]]&lt;br /&gt;
&lt;br /&gt;
== Performance analyses ==&lt;br /&gt;
* [[Execution on Intel® Xeon Phi™ co-processor]]&lt;br /&gt;
* [[1D MLSM and FDM comparison]]&lt;br /&gt;
* [[:File:tech_report.pdf|Execution overheads due to clumsy types::technical report]] [[File:pdf-file.gif]]&lt;br /&gt;
* [[Solving sparse systems]]&lt;br /&gt;
* [[Eigen paralelization]]&lt;br /&gt;
&lt;br /&gt;
== Last changes ==&lt;br /&gt;
&amp;lt;news unique=1 limit = 5&amp;gt;&lt;br /&gt;
*{{{timeanddate}}} :: {{{title}}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/news&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous ==&lt;br /&gt;
* FAQ  - [[Frequently asked questions]]. &lt;br /&gt;
* [[List of wiki contributors]]&lt;br /&gt;
* List of library contributors: [http://e6.ijs.si/medusa/about#about-contributors See the official website]&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
For pre-prints check https://e6.ijs.si/ParallelAndDistributedSystems/publications/&lt;br /&gt;
&lt;br /&gt;
* J. Slak, G. Kosec; Medusa : A C++ library for solving PDEs using strong form mesh-free methods, ACM transactions on mathematical software, vol. 47, 2021 [DOI: 10.1145/3450966]&lt;br /&gt;
* M. Depolli, J. Slak, G. Kosec; Parallel domain discretization algorithm for RBF-FD and other meshless numerical methods for solving PDEs, Computers &amp;amp; Structures, 2022 [DOI: 10.1016/j.compstruc.2022.106773]&lt;br /&gt;
* U. Duh, G. Kosec, J. Slak; Fast variable density node generation on parametric surfaces with application to mesh-free methods, SIAM journal on scientific computing, vol. 43, 2021 [DOI: 10.1137/20M1325642]&lt;br /&gt;
* M. Jančič, J. Slak, G. Kosec; Monomial augmentation guidelines for RBF-FD from accuracy versus computational time perspective, Journal of scientific computing, vol. 87, 2021 [DOI: 10.1007/s10915-020-01401-y]&lt;br /&gt;
* Slak J., Kosec G., On Generation of Node Distributions for Meshless PDE Discretizations, SIAM Journal on Scientific Computing, 41(5), A3202&lt;br /&gt;
* Slak J., Kosec G. Adaptive radial basis function-generated finite differences method for contact problems. International journal for numerical methods in engineering, ISSN 0029-5981 [http://www-e6.ijs.si/ParallelAndDistributedSystems/pdf/32230439.pdf manuscript]&lt;br /&gt;
* Slak J., Kosec G.; Refined meshless local strong form solution of Cauchy-Navier equation on an irregular domain. Engineering analysis with boundary elements. 2018;11 ; [http://comms.ijs.si/~gkosec/data/papers/31107623.pdf manuscript]&lt;br /&gt;
* Depolli, M., Kosec, G., Assessment of differential evolution for multi-objective optimization in a natural convection problem solved by a local meshless method. Engineering optimization, 2017, vol. 49, no. 4, pp. 675-692 ;[http://comms.ijs.si/~gkosec/data/papers/29639719.pdf manuscript]&lt;br /&gt;
* Kosec G., A local numerical solution of a fluid-flow problem on an irregular domain. Advances in engineering software. 2016;7 ; [29512743] ; [http://comms.ijs.si/~gkosec/data/papers/29512743.pdf manuscript]&lt;br /&gt;
* Kosec G., Trobec R., Simulation of semiconductor devices with a local numerical approach. Engineering analysis with boundary elements. 2015;69-75; [27912487] ; [http://comms.ijs.si/~gkosec/data/papers/27912487.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., Simulation of macrosegregation with mesosegregates in binary metallic casts by a meshless method. Engineering analysis with boundary elements. 2014;36-44; [http://comms.ijs.si/~gkosec/data/papers/3218939.pdf manuscript]&lt;br /&gt;
* Kosec G., Depolli M., Rashkovska A., Trobec R., Super linear speedup in a local parallel meshless solution of thermo-fluid problem. Computers &amp;amp; Structures. 2014;133:30-38; [http://comms.ijs.si/~gkosec/data/papers/27339815.pdf manuscript]&lt;br /&gt;
* Kosec G., Zinterhof P., Local strong form meshless method on multiple Graphics Processing Units. Computer modeling in engineering &amp;amp; sciences. 2013;91:377-396; [http://comms.ijs.si/~gkosec/data/papers/26785063.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., H-adaptive local radial basis function collocation meshless method. Computers, materials &amp;amp; continua. 2011;26:227-253; [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerBurgers.pdf manuscript]&lt;br /&gt;
* Trobec R., Kosec G., Šterk M., Šarler B., Comparison of local weak and strong form meshless methods for 2-D diffusion equation. Engineering analysis with boundary elements. 2012;36:310-321; [http://comms.ijs.si/~gkosec/data/papers/EABE2499.pdf manuscript]&lt;br /&gt;
* Kosec G, Zaloznik M, Sarler B, Combeau H. A Meshless Approach Towards Solution of Macrosegregation Phenomena. CMC: Computers, Materials, &amp;amp; Continua. 2011;580:1-27 [http://comms.ijs.si/~gkosec/data/papers/KosecZaloznikSarlerCombeauSegregation.pdf manuscript]&lt;br /&gt;
* Kosec G, Sarler B. Solution of thermo-fluid problems by collocation with local pressure correction. International Journal of Numerical Methods for Heat &amp;amp; Fluid Flow. 2008;18:868-82 [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerNS2008.pdf manuscript]&lt;br /&gt;
*  Trobec R., Kosec G., Parallel Scientific Computing, ISBN: 978-3-319-17072-5 (Print) 978-3-319-17073-2.&lt;br /&gt;
*  Slak, J., Kosec, G.. Detection of heart rate variability from a wearable differential ECG device., MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938, pp 450-455.&lt;br /&gt;
*  Kolman, M., Kosec, G. Correlation between attenuation of 20 GHz satellite communication link and liquid water content in the atmosphere. MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938. pp. 308-313.&lt;br /&gt;
&lt;br /&gt;
==Related pages==&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/products/medusa/&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3208</id>
		<title>Medusa</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3208"/>
				<updated>2022-07-04T15:05:26Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--__NOTITLE__--&amp;gt;&lt;br /&gt;
'''Welcome to the Medusa wiki. To visit the main website, go to [http://e6.ijs.si/medusa/ http://e6.ijs.si/medusa/].'''&lt;br /&gt;
&lt;br /&gt;
In [http://e6.ijs.si/ParallelAndDistributedSystems/ Parallel and Distributed Systems Laboratory] we are working on a C++ library that is first and foremost focused on tools for solving Partial Differential Equations by meshless methods. The basic idea is to create generic codes for tools that are needed for solving not only PDEs but many other problems, e.g. Moving Least Squares approximation, $k$-d tree, domain generation engines, etc.&lt;br /&gt;
We call this open source meshless project [http://e6.ijs.si/medusa/ Medusa: Coordinate Free Meshless Method implementation (MM)].&lt;br /&gt;
&lt;br /&gt;
Technical details about code and examples  can be found on our [http://e6.ijs.si/medusa/docs/ documentation page] and [https://gitlab.com/e62Lab/medusa Gitlab repository]. [[File:C.png|100px||link=https://gitlab.com/e62Lab/medusa|alt=Alt text|code]] [[File:doxygen.png|100px|link=http://e6.ijs.si/medusa/docs/|alt=Alt text|Documentation page]]&lt;br /&gt;
&lt;br /&gt;
This wiki site is meant for more relaxed discussions about general principles, possible and already implemented applications, preliminary analyses, etc.&lt;br /&gt;
Note, that there are many grammatical mistakes, typos, stupid sentences, etc. This wiki is meant for quick information exchange and therefore we do not invest a lot of energy into styling :).  &lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
* [https://gitlab.com/e62Lab/medusa Code on Gitlab]&lt;br /&gt;
* [[How to build | Installation and building]]&lt;br /&gt;
* [[Including this library in your project | Including this library in your project]]&lt;br /&gt;
* [[Testing | Running tests]]&lt;br /&gt;
* [http://e6.ijs.si/medusa/docs/ Technical documentation]&lt;br /&gt;
* [[Coding style | Coding style]]&lt;br /&gt;
* [[Wiki editing guide | Wiki editing and backup guide]]&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
In this section we present exact examples. Each of the below solutions can be found also in in the repository under examples. More explanation about the physical background and solution procedure can be found in following sections.&lt;br /&gt;
* [[Philosophy of examples and how to run them]]&lt;br /&gt;
* [[Poisson's equation]]&lt;br /&gt;
* [[Heat equation]]&lt;br /&gt;
* [[Linear elasticity]]&lt;br /&gt;
* [[Complex-valued problems]]&lt;br /&gt;
* [[Coupled domains]]&lt;br /&gt;
* [[Parametric domains | Parametric domains &amp;amp;ndash; Curved surface with variable density]]&lt;br /&gt;
* [[NURBS domains | Domains modeled with non-uniform rational basis spline's (NURBS)]]&lt;br /&gt;
* [[Determining the interior of the domain by oversampling the boundary]]&lt;br /&gt;
* [[Computer-aided design | Importing IGES and STEP files]]&lt;br /&gt;
* [[Realistic 3D models]]&lt;br /&gt;
* [[Customization]]&lt;br /&gt;
* [[Ghost nodes]]&lt;br /&gt;
* [[Electromagnetic scattering]]&lt;br /&gt;
* [[Schrödinger equation]]&lt;br /&gt;
* [[Wave equation]]&lt;br /&gt;
* [[Cahn-Hilliard equation]]&lt;br /&gt;
* [[Non-Newtonian_fluid_example | Non-Newtonian fluid]]&lt;br /&gt;
* [[Meshless Lattice Boltzmann method]]&lt;br /&gt;
&lt;br /&gt;
== Building blocks ==&lt;br /&gt;
Medusa is modular coordinate-free parallel implementation of a numerical framework designed, but not limited to, for solving PDEs. In this section we present main modules of the library that can be also used as a standalone tools. &lt;br /&gt;
* [[Positioning of computational nodes]] &lt;br /&gt;
* [[Relaxation of the nodal distribution]]&lt;br /&gt;
* [[Refinement of the nodal distribution]]&lt;br /&gt;
* [[k-d tree|''k''-d tree]] and other spatial search structures&lt;br /&gt;
* Solving [[Solving linear systems | linear systems]], [[Solving overdetermined systems | overdetermined]] and [[Solving underdetermined systems | underdetermined]]&lt;br /&gt;
* [[Weighted Least Squares (WLS)]]&lt;br /&gt;
* [[Computation of shape functions]]&lt;br /&gt;
* [[Meshless Local Strong Form Method (MLSM)]]&lt;br /&gt;
* [[Radial basis function-generated finite differences (RBF-FD)]]&lt;br /&gt;
* [[Ghost nodes (theory)]]&lt;br /&gt;
* [[Integrators for time stepping]]&lt;br /&gt;
* [[RBF Interpolation]]&lt;br /&gt;
&lt;br /&gt;
== Discussions / Applications ==&lt;br /&gt;
This section is meant for general discussion about the physical background of the examples, the solution procedures, various applications, etc. Note, that code snippets presented in discussion might not reflect the actual state of Medusa.  &lt;br /&gt;
* [[Convection Diffusion equation | Convection Diffusion equation]]&lt;br /&gt;
* [[Adaptivity]]&lt;br /&gt;
* [[Solid Mechanics]]&lt;br /&gt;
** [[Point contact]]&lt;br /&gt;
** [[Hertzian contact]]&lt;br /&gt;
** [[Cantilever beam]]&lt;br /&gt;
** [[Fretting fatigue case]]&lt;br /&gt;
** [[Plasticity]]&lt;br /&gt;
* [[Fluid Mechanics]]&lt;br /&gt;
** [[Lid driven cavity]]&lt;br /&gt;
** [[de Vahl Davis natural convection test]]&lt;br /&gt;
** [[Natural convection in 3D irregular domain]]&lt;br /&gt;
** [[Natural convection from heated cylinder]]&lt;br /&gt;
** [[Natural convection between concentric cylinders]]&lt;br /&gt;
** [[Non-Newtonian fluid]]&lt;br /&gt;
* [[Computational electromagnetics]]&lt;br /&gt;
** [[Triple dielectric step in 1D]]&lt;br /&gt;
** [[Scattering from an infinite cylinder]]&lt;br /&gt;
** [[Point source near an anisotropic lens]]&lt;br /&gt;
* Other applications&lt;br /&gt;
** [[Attenuation due to liquid water content in the atmosphere|Attenuation of a satellite communication]]&lt;br /&gt;
** [[Heart rate variability detection]]&lt;br /&gt;
** [[Bioheat equation]]&lt;br /&gt;
&lt;br /&gt;
== Performance analyses ==&lt;br /&gt;
* [[Execution on Intel® Xeon Phi™ co-processor]]&lt;br /&gt;
* [[1D MLSM and FDM comparison]]&lt;br /&gt;
* [[:File:tech_report.pdf|Execution overheads due to clumsy types::technical report]] [[File:pdf-file.gif]]&lt;br /&gt;
* [[Solving sparse systems]]&lt;br /&gt;
* [[Eigen paralelization]]&lt;br /&gt;
&lt;br /&gt;
== Last changes ==&lt;br /&gt;
&amp;lt;news unique=1 limit = 5&amp;gt;&lt;br /&gt;
*{{{timeanddate}}} :: {{{title}}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/news&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous ==&lt;br /&gt;
* FAQ  - [[Frequently asked questions]]. &lt;br /&gt;
* [[List of wiki contributors]]&lt;br /&gt;
* List of library contributors: [http://e6.ijs.si/medusa/about#about-contributors See the official website]&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
For pre-prints check https://e6.ijs.si/ParallelAndDistributedSystems/publications/&lt;br /&gt;
&lt;br /&gt;
* J. Slak, G. Kosec; Medusa : A C++ library for solving PDEs using strong form mesh-free methods, ACM transactions on mathematical software, vol. 47, 2021 [DOI: 10.1145/3450966]&lt;br /&gt;
* M. Depolli, J. Slak, G. Kosec; Parallel domain discretization algorithm for RBF-FD and other meshless numerical methods for solving PDEs, Computers &amp;amp; Structures, 2022 [DOI: 10.1016/j.compstruc.2022.106773]&lt;br /&gt;
* U. Duh, G. Kosec, J. Slak; Fast variable density node generation on parametric surfaces with application to mesh-free methods, SIAM journal on scientific computing, vol. 43, 2021 [DOI: 10.1137/20M1325642]&lt;br /&gt;
* M. Jančič, J. Slak, G. Kosec; Monomial augmentation guidelines for RBF-FD from accuracy versus computational time perspective, Journal of scientific computing, vol. 87, 2021 [DOI: 10.1007/s10915-020-01401-y]&lt;br /&gt;
* Slak J., Kosec G., On Generation of Node Distributions for Meshless PDE Discretizations, SIAM Journal on Scientific Computing, 41(5), A3202&lt;br /&gt;
* Slak J., Kosec G. Adaptive radial basis function-generated finite differences method for contact problems. International journal for numerical methods in engineering, ISSN 0029-5981 [http://www-e6.ijs.si/ParallelAndDistributedSystems/pdf/32230439.pdf manuscript]&lt;br /&gt;
* Slak J., Kosec G.; Refined meshless local strong form solution of Cauchy-Navier equation on an irregular domain. Engineering analysis with boundary elements. 2018;11 ; [http://comms.ijs.si/~gkosec/data/papers/31107623.pdf manuscript]&lt;br /&gt;
* Depolli, M., Kosec, G., Assessment of differential evolution for multi-objective optimization in a natural convection problem solved by a local meshless method. Engineering optimization, 2017, vol. 49, no. 4, pp. 675-692 ;[http://comms.ijs.si/~gkosec/data/papers/29639719.pdf manuscript]&lt;br /&gt;
* Kosec G., A local numerical solution of a fluid-flow problem on an irregular domain. Advances in engineering software. 2016;7 ; [29512743] ; [http://comms.ijs.si/~gkosec/data/papers/29512743.pdf manuscript]&lt;br /&gt;
* Kosec G., Trobec R., Simulation of semiconductor devices with a local numerical approach. Engineering analysis with boundary elements. 2015;69-75; [27912487] ; [http://comms.ijs.si/~gkosec/data/papers/27912487.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., Simulation of macrosegregation with mesosegregates in binary metallic casts by a meshless method. Engineering analysis with boundary elements. 2014;36-44; [http://comms.ijs.si/~gkosec/data/papers/3218939.pdf manuscript]&lt;br /&gt;
* Kosec G., Depolli M., Rashkovska A., Trobec R., Super linear speedup in a local parallel meshless solution of thermo-fluid problem. Computers &amp;amp; Structures. 2014;133:30-38; [http://comms.ijs.si/~gkosec/data/papers/27339815.pdf manuscript]&lt;br /&gt;
* Kosec G., Zinterhof P., Local strong form meshless method on multiple Graphics Processing Units. Computer modeling in engineering &amp;amp; sciences. 2013;91:377-396; [http://comms.ijs.si/~gkosec/data/papers/26785063.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., H-adaptive local radial basis function collocation meshless method. Computers, materials &amp;amp; continua. 2011;26:227-253; [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerBurgers.pdf manuscript]&lt;br /&gt;
* Trobec R., Kosec G., Šterk M., Šarler B., Comparison of local weak and strong form meshless methods for 2-D diffusion equation. Engineering analysis with boundary elements. 2012;36:310-321; [http://comms.ijs.si/~gkosec/data/papers/EABE2499.pdf manuscript]&lt;br /&gt;
* Kosec G, Zaloznik M, Sarler B, Combeau H. A Meshless Approach Towards Solution of Macrosegregation Phenomena. CMC: Computers, Materials, &amp;amp; Continua. 2011;580:1-27 [http://comms.ijs.si/~gkosec/data/papers/KosecZaloznikSarlerCombeauSegregation.pdf manuscript]&lt;br /&gt;
* Kosec G, Sarler B. Solution of thermo-fluid problems by collocation with local pressure correction. International Journal of Numerical Methods for Heat &amp;amp; Fluid Flow. 2008;18:868-82 [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerNS2008.pdf manuscript]&lt;br /&gt;
*  Trobec R., Kosec G., Parallel Scientific Computing, ISBN: 978-3-319-17072-5 (Print) 978-3-319-17073-2.&lt;br /&gt;
*  Slak, J., Kosec, G.. Detection of heart rate variability from a wearable differential ECG device., MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938, pp 450-455.&lt;br /&gt;
*  Kolman, M., Kosec, G. Correlation between attenuation of 20 GHz satellite communication link and liquid water content in the atmosphere. MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938. pp. 308-313.&lt;br /&gt;
&lt;br /&gt;
==Related pages==&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/products/medusa/&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Determining_the_interior_of_the_domain_by_oversampling_the_boundary&amp;diff=3207</id>
		<title>Determining the interior of the domain by oversampling the boundary</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Determining_the_interior_of_the_domain_by_oversampling_the_boundary&amp;diff=3207"/>
				<updated>2022-07-04T13:29:37Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Go back to [[Medusa#Examples|Examples]].&lt;br /&gt;
&lt;br /&gt;
Sometimes, the interior of a complex domain cannot be correctly determined from the discretized boundary, leading to points &amp;quot;leaking&amp;quot; out of the domain. This can for example happen with the duck model shown in [[NURBS domains]] if it is sampled with small node density (big spacing $h$).&lt;br /&gt;
&lt;br /&gt;
[[File:leaking_domain.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The easiest way to deal with this problem is to sample the boundary with a higher node density (smaller spacing $h$) and use this oversampled discretization when querying for the interior of the domain. This usage is supported by &amp;lt;code&amp;gt;GeneralFill&amp;lt;/code&amp;gt; (see [[Positioning of computational nodes]]) and can be implemented by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Oversample the domain.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; oversampled_domain = shape.discretizeBoundaryWithStep(h / 5);&lt;br /&gt;
&lt;br /&gt;
// Construct the contains function.&lt;br /&gt;
KDTree&amp;lt;Vec2d&amp;gt; contains_tree;&lt;br /&gt;
oversampled_domain.makeDiscreteContainsStructure(contains_tree);&lt;br /&gt;
auto contains_function = [&amp;amp;] (const Vec2d p) {&lt;br /&gt;
    return oversampled_domain.discreteContains(p, contains_tree);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Fill the boundary normally.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; domain = shape.discretizeBoundaryWithStep(h);&lt;br /&gt;
&lt;br /&gt;
// Fill the interior with the contains function.&lt;br /&gt;
KDTreeMutable&amp;lt;Vec2d&amp;gt; tree;&lt;br /&gt;
GeneralFill&amp;lt;Vec2d&amp;gt; gf;&lt;br /&gt;
gf(domain, h, tree, contains_function);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we have decreased the spacing by 5 in the oversampled domain. For higher node densities, less oversampling also works. The above procedure results in&lt;br /&gt;
&lt;br /&gt;
[[File:oversampled_domain.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The whole example can be found as inside_by_oversampling.cpp along with the plot script that can be run by Matlab or Octave inside_by_oversampling.m.&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Determining_the_interior_of_the_domain_by_oversampling_the_boundary&amp;diff=3206</id>
		<title>Determining the interior of the domain by oversampling the boundary</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Determining_the_interior_of_the_domain_by_oversampling_the_boundary&amp;diff=3206"/>
				<updated>2022-07-04T13:27:18Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Go back to [[Medusa#Examples|Examples]].&lt;br /&gt;
&lt;br /&gt;
Sometimes, the interior of a complex domain cannot be correctly determined from the discretized boundary, leading to points &amp;quot;leaking&amp;quot; out of the domain. This can for example happen with the duck model shown in [[NURBS domains]] if it is sampled with small node density (big spacing $h$).&lt;br /&gt;
&lt;br /&gt;
[[File:leaking_domain.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The easiest way to deal with this problem is to sample the boundary with a higher node density (smaller spacing $h$) and use this oversampled discretization when querying for the interior of the domain. This usage is supported by &amp;lt;code&amp;gt;GeneralFill&amp;lt;/code&amp;gt; (see [[Positioning of computational nodes]]) and can be implemented by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Oversample the domain.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; oversampled_domain = shape.discretizeBoundaryWithStep(h / 5);&lt;br /&gt;
&lt;br /&gt;
// Construct the contains function.&lt;br /&gt;
KDTree&amp;lt;Vec2d&amp;gt; contains_tree;&lt;br /&gt;
oversampled_domain.makeDiscreteContainsStructure(contains_tree);&lt;br /&gt;
auto contains_function = [&amp;amp;] (const Vec2d p) {&lt;br /&gt;
    return oversampled_domain.discreteContains(p, contains_tree);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Fill the boundary normally.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; domain = shape.discretizeBoundaryWithStep(h);&lt;br /&gt;
&lt;br /&gt;
// Fill the interior with the contains function.&lt;br /&gt;
KDTreeMutable&amp;lt;Vec2d&amp;gt; tree;&lt;br /&gt;
GeneralFill&amp;lt;Vec2d&amp;gt; gf;&lt;br /&gt;
gf(domain, h, tree, contains_function);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we have decreased the spacing by 5 in the oversampled domain. For higher node densities, less oversampling also works. The above procedure results in&lt;br /&gt;
&lt;br /&gt;
[[File:oversampled_domain.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The whole example can be found as [https://gitlab.com/e62Lab/medusa/-/blob/dev/examples/poisson_equation TODO.cpp] along with the plot script that can be run by Matlab or Octave [https://gitlab.com/e62Lab/medusa/-/blob/dev/examples/poisson_equation TODO.m].&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Determining_the_interior_of_the_domain_by_oversampling_the_boundary&amp;diff=3205</id>
		<title>Determining the interior of the domain by oversampling the boundary</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Determining_the_interior_of_the_domain_by_oversampling_the_boundary&amp;diff=3205"/>
				<updated>2022-07-04T13:24:05Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: Created page with &amp;quot;Go back to Examples.  Sometimes, the interior of a complex domain cannot be correctly determined from the discretized boundary, leading to points &amp;quot;leaking&amp;quot;...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Go back to [[Medusa#Examples|Examples]].&lt;br /&gt;
&lt;br /&gt;
Sometimes, the interior of a complex domain cannot be correctly determined from the discretized boundary, leading to points &amp;quot;leaking&amp;quot; out of the domain. This can for example happen with the duck model shown in [[NURBS domains]] if it is sampled with small node density (big spacing $h$).&lt;br /&gt;
&lt;br /&gt;
[[File:leaking_domain.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The easiest way to deal with this problem is to sample the boundary with a higher node density (smaller spacing $h$) and use this oversampled discretization when querying for the interior of the domain. This usage is supported by &amp;lt;code&amp;gt;GeneralFill&amp;lt;/code&amp;gt; (see [[Positioning of computational nodes]]) and can be implemented by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Construct the contains function.&lt;br /&gt;
KDTree&amp;lt;Vec2d&amp;gt; contains_tree;&lt;br /&gt;
oversampled_domain.makeDiscreteContainsStructure(contains_tree);&lt;br /&gt;
auto contains_function = [&amp;amp;] (const Vec2d p) {&lt;br /&gt;
    return oversampled_domain.discreteContains(p, contains_tree);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// Fill the boundary normally.&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; domain = shape.discretizeBoundaryWithStep(h);&lt;br /&gt;
&lt;br /&gt;
// Fill the interior with the contains function.&lt;br /&gt;
KDTreeMutable&amp;lt;Vec2d&amp;gt; tree;&lt;br /&gt;
GeneralFill&amp;lt;Vec2d&amp;gt; gf;&lt;br /&gt;
gf(domain, h, tree, contains_function);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above procedure results in&lt;br /&gt;
&lt;br /&gt;
[[File:oversampled_domain.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The whole example can be found as [https://gitlab.com/e62Lab/medusa/-/blob/dev/examples/poisson_equation TODO.cpp] along with the plot script that can be run by Matlab or Octave [https://gitlab.com/e62Lab/medusa/-/blob/dev/examples/poisson_equation TODO.m].&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Oversampled_domain.png&amp;diff=3204</id>
		<title>File:Oversampled domain.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Oversampled_domain.png&amp;diff=3204"/>
				<updated>2022-07-04T13:23:30Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Leaking_domain.png&amp;diff=3203</id>
		<title>File:Leaking domain.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Leaking_domain.png&amp;diff=3203"/>
				<updated>2022-07-04T13:15:19Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3202</id>
		<title>Medusa</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3202"/>
				<updated>2022-07-04T13:11:38Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--__NOTITLE__--&amp;gt;&lt;br /&gt;
'''Welcome to the Medusa wiki. To visit the main website, go to [http://e6.ijs.si/medusa/ http://e6.ijs.si/medusa/].'''&lt;br /&gt;
&lt;br /&gt;
In [http://e6.ijs.si/ParallelAndDistributedSystems/ Parallel and Distributed Systems Laboratory] we are working on a C++ library that is first and foremost focused on tools for solving Partial Differential Equations by meshless methods. The basic idea is to create generic codes for tools that are needed for solving not only PDEs but many other problems, e.g. Moving Least Squares approximation, $k$-d tree, domain generation engines, etc.&lt;br /&gt;
We call this open source meshless project [http://e6.ijs.si/medusa/ Medusa: Coordinate Free Meshless Method implementation (MM)].&lt;br /&gt;
&lt;br /&gt;
Technical details about code and examples  can be found on our [http://e6.ijs.si/medusa/docs/ documentation page] and [https://gitlab.com/e62Lab/medusa Gitlab repository]. [[File:C.png|100px||link=https://gitlab.com/e62Lab/medusa|alt=Alt text|code]] [[File:doxygen.png|100px|link=http://e6.ijs.si/medusa/docs/|alt=Alt text|Documentation page]]&lt;br /&gt;
&lt;br /&gt;
This wiki site is meant for more relaxed discussions about general principles, possible and already implemented applications, preliminary analyses, etc.&lt;br /&gt;
Note, that there are many grammatical mistakes, typos, stupid sentences, etc. This wiki is meant for quick information exchange and therefore we do not invest a lot of energy into styling :).  &lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
* [https://gitlab.com/e62Lab/medusa Code on Gitlab]&lt;br /&gt;
* [[How to build | Installation and building]]&lt;br /&gt;
* [[Including this library in your project | Including this library in your project]]&lt;br /&gt;
* [[Testing | Running tests]]&lt;br /&gt;
* [http://e6.ijs.si/medusa/docs/ Technical documentation]&lt;br /&gt;
* [[Coding style | Coding style]]&lt;br /&gt;
* [[Wiki editing guide | Wiki editing and backup guide]]&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
In this section we present exact examples. Each of the below solutions can be found also in in the repository under examples. More explanation about the physical background and solution procedure can be found in following sections.&lt;br /&gt;
* [[Philosophy of examples and how to run them]]&lt;br /&gt;
* [[Poisson's equation]]&lt;br /&gt;
* [[Heat equation]]&lt;br /&gt;
* [[Linear elasticity]]&lt;br /&gt;
* [[Complex-valued problems]]&lt;br /&gt;
* [[Coupled domains]]&lt;br /&gt;
* [[Parametric domains | Parametric domains &amp;amp;ndash; Curved surface with variable density]]&lt;br /&gt;
* [[NURBS domains | Domains modeled with non-uniform rational basis spline's (NURBS)]]&lt;br /&gt;
* [[Determining the interior of the domain by oversampling the boundary]]&lt;br /&gt;
* [[Realistic 3D models]]&lt;br /&gt;
* [[Customization]]&lt;br /&gt;
* [[Ghost nodes]]&lt;br /&gt;
* [[Electromagnetic scattering]]&lt;br /&gt;
* [[Schrödinger equation]]&lt;br /&gt;
* [[Wave equation]]&lt;br /&gt;
* [[Cahn-Hilliard equation]]&lt;br /&gt;
* [[Non-Newtonian_fluid_example | Non-Newtonian fluid]]&lt;br /&gt;
* [[Meshless Lattice Boltzmann method]]&lt;br /&gt;
&lt;br /&gt;
== Building blocks ==&lt;br /&gt;
Medusa is modular coordinate-free parallel implementation of a numerical framework designed, but not limited to, for solving PDEs. In this section we present main modules of the library that can be also used as a standalone tools. &lt;br /&gt;
* [[Positioning of computational nodes]] &lt;br /&gt;
* [[Relaxation of the nodal distribution]]&lt;br /&gt;
* [[Refinement of the nodal distribution]]&lt;br /&gt;
* [[k-d tree|''k''-d tree]] and other spatial search structures&lt;br /&gt;
* Solving [[Solving linear systems | linear systems]], [[Solving overdetermined systems | overdetermined]] and [[Solving underdetermined systems | underdetermined]]&lt;br /&gt;
* [[Weighted Least Squares (WLS)]]&lt;br /&gt;
* [[Computation of shape functions]]&lt;br /&gt;
* [[Meshless Local Strong Form Method (MLSM)]]&lt;br /&gt;
* [[Radial basis function-generated finite differences (RBF-FD)]]&lt;br /&gt;
* [[Ghost nodes (theory)]]&lt;br /&gt;
* [[Integrators for time stepping]]&lt;br /&gt;
* [[RBF Interpolation]]&lt;br /&gt;
&lt;br /&gt;
== Discussions / Applications ==&lt;br /&gt;
This section is meant for general discussion about the physical background of the examples, the solution procedures, various applications, etc. Note, that code snippets presented in discussion might not reflect the actual state of Medusa.  &lt;br /&gt;
* [[Convection Diffusion equation | Convection Diffusion equation]]&lt;br /&gt;
* [[Adaptivity]]&lt;br /&gt;
* [[Solid Mechanics]]&lt;br /&gt;
** [[Point contact]]&lt;br /&gt;
** [[Hertzian contact]]&lt;br /&gt;
** [[Cantilever beam]]&lt;br /&gt;
** [[Fretting fatigue case]]&lt;br /&gt;
** [[Plasticity]]&lt;br /&gt;
* [[Fluid Mechanics]]&lt;br /&gt;
** [[Lid driven cavity]]&lt;br /&gt;
** [[de Vahl Davis natural convection test]]&lt;br /&gt;
** [[Natural convection in 3D irregular domain]]&lt;br /&gt;
** [[Natural convection from heated cylinder]]&lt;br /&gt;
** [[Natural convection between concentric cylinders]]&lt;br /&gt;
** [[Non-Newtonian fluid]]&lt;br /&gt;
* [[Computational electromagnetics]]&lt;br /&gt;
** [[Triple dielectric step in 1D]]&lt;br /&gt;
** [[Scattering from an infinite cylinder]]&lt;br /&gt;
** [[Point source near an anisotropic lens]]&lt;br /&gt;
* Other applications&lt;br /&gt;
** [[Attenuation due to liquid water content in the atmosphere|Attenuation of a satellite communication]]&lt;br /&gt;
** [[Heart rate variability detection]]&lt;br /&gt;
** [[Bioheat equation]]&lt;br /&gt;
&lt;br /&gt;
== Performance analyses ==&lt;br /&gt;
* [[Execution on Intel® Xeon Phi™ co-processor]]&lt;br /&gt;
* [[1D MLSM and FDM comparison]]&lt;br /&gt;
* [[:File:tech_report.pdf|Execution overheads due to clumsy types::technical report]] [[File:pdf-file.gif]]&lt;br /&gt;
* [[Solving sparse systems]]&lt;br /&gt;
* [[Eigen paralelization]]&lt;br /&gt;
&lt;br /&gt;
== Last changes ==&lt;br /&gt;
&amp;lt;news unique=1 limit = 5&amp;gt;&lt;br /&gt;
*{{{timeanddate}}} :: {{{title}}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/news&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous ==&lt;br /&gt;
* FAQ  - [[Frequently asked questions]]. &lt;br /&gt;
* [[List of wiki contributors]]&lt;br /&gt;
* List of library contributors: [http://e6.ijs.si/medusa/about#about-contributors See the official website]&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
For pre-prints check https://e6.ijs.si/ParallelAndDistributedSystems/publications/&lt;br /&gt;
&lt;br /&gt;
* J. Slak, G. Kosec; Medusa : A C++ library for solving PDEs using strong form mesh-free methods, ACM transactions on mathematical software, vol. 47, 2021 [DOI: 10.1145/3450966]&lt;br /&gt;
* M. Depolli, J. Slak, G. Kosec; Parallel domain discretization algorithm for RBF-FD and other meshless numerical methods for solving PDEs, Computers &amp;amp; Structures, 2022 [DOI: 10.1016/j.compstruc.2022.106773]&lt;br /&gt;
* U. Duh, G. Kosec, J. Slak; Fast variable density node generation on parametric surfaces with application to mesh-free methods, SIAM journal on scientific computing, vol. 43, 2021 [DOI: 10.1137/20M1325642]&lt;br /&gt;
* M. Jančič, J. Slak, G. Kosec; Monomial augmentation guidelines for RBF-FD from accuracy versus computational time perspective, Journal of scientific computing, vol. 87, 2021 [DOI: 10.1007/s10915-020-01401-y]&lt;br /&gt;
* Slak J., Kosec G., On Generation of Node Distributions for Meshless PDE Discretizations, SIAM Journal on Scientific Computing, 41(5), A3202&lt;br /&gt;
* Slak J., Kosec G. Adaptive radial basis function-generated finite differences method for contact problems. International journal for numerical methods in engineering, ISSN 0029-5981 [http://www-e6.ijs.si/ParallelAndDistributedSystems/pdf/32230439.pdf manuscript]&lt;br /&gt;
* Slak J., Kosec G.; Refined meshless local strong form solution of Cauchy-Navier equation on an irregular domain. Engineering analysis with boundary elements. 2018;11 ; [http://comms.ijs.si/~gkosec/data/papers/31107623.pdf manuscript]&lt;br /&gt;
* Depolli, M., Kosec, G., Assessment of differential evolution for multi-objective optimization in a natural convection problem solved by a local meshless method. Engineering optimization, 2017, vol. 49, no. 4, pp. 675-692 ;[http://comms.ijs.si/~gkosec/data/papers/29639719.pdf manuscript]&lt;br /&gt;
* Kosec G., A local numerical solution of a fluid-flow problem on an irregular domain. Advances in engineering software. 2016;7 ; [29512743] ; [http://comms.ijs.si/~gkosec/data/papers/29512743.pdf manuscript]&lt;br /&gt;
* Kosec G., Trobec R., Simulation of semiconductor devices with a local numerical approach. Engineering analysis with boundary elements. 2015;69-75; [27912487] ; [http://comms.ijs.si/~gkosec/data/papers/27912487.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., Simulation of macrosegregation with mesosegregates in binary metallic casts by a meshless method. Engineering analysis with boundary elements. 2014;36-44; [http://comms.ijs.si/~gkosec/data/papers/3218939.pdf manuscript]&lt;br /&gt;
* Kosec G., Depolli M., Rashkovska A., Trobec R., Super linear speedup in a local parallel meshless solution of thermo-fluid problem. Computers &amp;amp; Structures. 2014;133:30-38; [http://comms.ijs.si/~gkosec/data/papers/27339815.pdf manuscript]&lt;br /&gt;
* Kosec G., Zinterhof P., Local strong form meshless method on multiple Graphics Processing Units. Computer modeling in engineering &amp;amp; sciences. 2013;91:377-396; [http://comms.ijs.si/~gkosec/data/papers/26785063.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., H-adaptive local radial basis function collocation meshless method. Computers, materials &amp;amp; continua. 2011;26:227-253; [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerBurgers.pdf manuscript]&lt;br /&gt;
* Trobec R., Kosec G., Šterk M., Šarler B., Comparison of local weak and strong form meshless methods for 2-D diffusion equation. Engineering analysis with boundary elements. 2012;36:310-321; [http://comms.ijs.si/~gkosec/data/papers/EABE2499.pdf manuscript]&lt;br /&gt;
* Kosec G, Zaloznik M, Sarler B, Combeau H. A Meshless Approach Towards Solution of Macrosegregation Phenomena. CMC: Computers, Materials, &amp;amp; Continua. 2011;580:1-27 [http://comms.ijs.si/~gkosec/data/papers/KosecZaloznikSarlerCombeauSegregation.pdf manuscript]&lt;br /&gt;
* Kosec G, Sarler B. Solution of thermo-fluid problems by collocation with local pressure correction. International Journal of Numerical Methods for Heat &amp;amp; Fluid Flow. 2008;18:868-82 [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerNS2008.pdf manuscript]&lt;br /&gt;
*  Trobec R., Kosec G., Parallel Scientific Computing, ISBN: 978-3-319-17072-5 (Print) 978-3-319-17073-2.&lt;br /&gt;
*  Slak, J., Kosec, G.. Detection of heart rate variability from a wearable differential ECG device., MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938, pp 450-455.&lt;br /&gt;
*  Kolman, M., Kosec, G. Correlation between attenuation of 20 GHz satellite communication link and liquid water content in the atmosphere. MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938. pp. 308-313.&lt;br /&gt;
&lt;br /&gt;
==Related pages==&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/products/medusa/&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Relaxation_of_the_nodal_distribution&amp;diff=3078</id>
		<title>Relaxation of the nodal distribution</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Relaxation_of_the_nodal_distribution&amp;diff=3078"/>
				<updated>2020-09-15T19:04:12Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To construct stable and reliable shape functions the support domains need to be non-degenerated &amp;lt;ref name=&amp;quot;LeeLocal&amp;quot;&amp;gt;Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409.&amp;lt;/ref&amp;gt;, i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes &amp;lt;ref name=&amp;quot;LohnerGeneral&amp;quot;&amp;gt;Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;LiuNode&amp;quot;&amp;gt;Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&amp;lt;/ref&amp;gt;, see [[Positioning of computational nodes]] for our algorithms. Here, an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \b{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;BasicRelax&amp;lt;/code&amp;gt; engine  supports two call types:&lt;br /&gt;
* with supplied distribution function &amp;lt;code&amp;gt;relax(domain, func)&amp;lt;/code&amp;gt;, where it tries to satisfy the user supplied nodal density function &amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with &amp;lt;code&amp;gt;GeneralFill&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;GeneralSurfaceFill&amp;lt;/code&amp;gt;.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing a 2D domain can be found in below code snippet and Figures. Note the difference between relax without supplied distribution (&amp;lt;xr id=&amp;quot;fig:relax_uniform&amp;quot;/&amp;gt;) and with supplied distribution (&amp;lt;xr id=&amp;quot;fig:relax_non-uniform&amp;quot;/&amp;gt;). These examples are extreme, relaxation is usually used to convert an almost desirable node distribution into a desirable node distribution.&lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Define domain shape.&lt;br /&gt;
double r = 0.25;&lt;br /&gt;
BallShape&amp;lt;Vec2d&amp;gt; bs({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
// Fill domain disretization with h.&lt;br /&gt;
auto h = [](Vec2d p){&lt;br /&gt;
    return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
};&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; domain = bs.discretizeBoundaryWithDensity(h);&lt;br /&gt;
GeneralFill&amp;lt;Vec2d&amp;gt; gf;&lt;br /&gt;
gf(domain, h);&lt;br /&gt;
&lt;br /&gt;
// Relax domain to uniform distribution.&lt;br /&gt;
BasicRelax relax;&lt;br /&gt;
relax.iterations(1000).initialHeat(1).finalHeat(0).boundaryProjectionThreshold(0.75)&lt;br /&gt;
     .projectionType(BasicRelax::PROJECT_IN_DIRECTION).numNeighbours(5);&lt;br /&gt;
relax(domain);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:relax_uniform&amp;quot;&amp;gt;&lt;br /&gt;
[[File:relax_uniform.png|thumb|center|800px|&amp;lt;caption&amp;gt; Relaxation of a non-uniform node distribution to a uniform node distribution. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:relax_non-uniform&amp;quot;&amp;gt;&lt;br /&gt;
[[File:relax_non-uniform.png|thumb|center|800px|&amp;lt;caption&amp;gt; Relaxation of a uniform node distribution to a non-uniform node distribution. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3077</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3077"/>
				<updated>2020-09-15T12:24:30Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithms below. Their goal is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p}): \Omega \to (0, \infty)$, which maps points from $\Omega$ to desired distance to neighboring points.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. It is therefore desirable that all the normalised above quantities are approximately equal to $1$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. For example, a desirable distribution of $\bar{d}'_i$ would have maximum and average approximately equal to $1$ and a low standard deviation. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can also be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
Those can also be normalized, getting $r' = r / h$. It is desirable that both $r'_\max$ and $r'_\min$ are approximately equal to $\frac{1}{2}$, however values of $r_\max$ around $2$ (especially when $N$ is small) are also considered good enough. In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior ==&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of $n$ new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Nearest neighbor search is performed by a spatial search structure, usually a [[K-d tree|''k''-d tree]] is used. Remaining candidates are enqueued and node $\b{p}_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a unit square can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gf_examples_2&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Examples of 2D domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The interior filling algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralFill.html GeneralFill].&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; for a distribution of normalized average distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right) filled with constant $h$. The distribution is satisfactory, since it has a lower standard deviation and maximum around $1$. See also the table below for other global measures of regularity for the same cases as those on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right) filled with constant $h$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0416$&lt;br /&gt;
|$0.0344$&lt;br /&gt;
|$0.0832$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.0656$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0508$&lt;br /&gt;
|$0.0418$&lt;br /&gt;
|$0.0849$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.1023$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Computational complexity  of the interior filling algorithm is&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
and when using a uniform-grid based spatial search structure&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; ([http://e6.ijs.si/medusa/docs/html/classmm_1_1KDGrid.html KDGrid] in Medusa) it simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, grid}} = O\left(\frac{|\text{obb} \Omega|}{|\Omega|}N + nN\right),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\text{obb} \Omega$ is the oriented bounding box of $\Omega$.&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling a box with a hole with roughly $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: $1.57$ s, of which $5\%$ is candidate generation, $85\%$ is spatial queries and $4\%$ is spatial inserts&lt;br /&gt;
* 2D, KDGrid: $0.35$ s, of which $19\%$ is candidate generation, $56\%$ is spatial queries and $0.002\%$ is spatial inserts&lt;br /&gt;
* 3D, KDTree: $7.87$ s, of which $6\%$ is candidate generation, $89\%$ is spatial queries and $1\%$ is spatial inserts&lt;br /&gt;
* 3D, KDGrid: $2.58$ s, of which $16\%$ is candidate generation, $70\%$ is spatial queries and $0.001\%$ is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with $N$, with larger $N$ increasing spatial query share by $2$ percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}.&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere and $|S_i| = n$. Now, we can accept candidates that are at least $h(\b{r}(\b{\lambda}_i))$ away from $\b{r}(\b{\lambda}_i)$ and enqueue them for expansion. The boundary filling algorithm terminates when the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a part of a unit sphere can be seen in &amp;lt;xr id=&amp;quot;fig:gsf_generation&amp;quot;/&amp;gt; &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the boundary filling algorithm in parametric domain $\Lambda$ (bottom) and main domain $\partial \Omega$ (top). Part of a unit sphere was discretized with $h = 0.08$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, &amp;lt;xr id=&amp;quot;fig:gsf_examples_2&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, for examples of discretized curves in 2D and surfaces in 3D.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_2d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 2D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_simple.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_3d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The boundary filling algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries. &lt;br /&gt;
&lt;br /&gt;
The algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralSurfaceFill.html GeneralSurfaceFill]. See also [[parametric domains]] example and [[NURBS domains]] example.&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt; for a distribution of normalized average distances to $c = 2$ nearest neighbors in 2D on a curve from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; (left) and $c = 3$ nearest neighbors in 3D on a heart-like surface from &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; (right) filled with constant $h$. The distribution is satisfactory, since it has a low standard deviation and maximum around $1$. It is even further improved for bigger $N$ (smaller $h$). See also the table below for other global measures of regularity for the same cases as those on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 2$ nearest neighbors in 2D (left) and $c = 3$ nearest neighbors in 3D (right) filled with constant $h$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0001$&lt;br /&gt;
|$5.1483 \times 10^{-4}$&lt;br /&gt;
|$1.1136 \times 10^{-10}$&lt;br /&gt;
|$0.4622$&lt;br /&gt;
|$0.7808$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0357$&lt;br /&gt;
|$0.0374$&lt;br /&gt;
|$3.8888 \times 10^{-4}$&lt;br /&gt;
|$0.3522$&lt;br /&gt;
|$1.5730$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Since the boundary filling algorithm is based on the interior filling algorithm, its computational complexity is also equal to&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling examples from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; with $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D ($n = 2$): $0.28$ s&lt;br /&gt;
* 3D ($n = 15$): $1.32$ s &lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3076</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3076"/>
				<updated>2020-09-15T11:12:02Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithms below. Their goal is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p}): \Omega \to (0, \infty)$, which maps points from $\Omega$ to desired distance to neighboring points.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. It is therefore desirable that all the normalised above quantities are approximately equal to $1$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. For example, a desirable distribution of $\bar{d}'_i$ would have maximum and average approximately equal to $1$ and a low standard deviation. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can also be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
Those can also be normalized, getting $r' = r / h$. It is desirable that both $r'_\max$ and $r'_\min$ are approximately equal to $\frac{1}{2}$, however values of $r_\max$ around $2$ (especially when $N$ is small) are also considered good enough. In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior ==&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of $n$ new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Nearest neighbor search is performed by a spatial search structure, usually a [[K-d tree|''k''-d tree]] is used. Remaining candidates are enqueued and node $\b{p}_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a unit square can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gf_examples_2&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Examples of 2D domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The interior filling algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralFill.html GeneralFill].&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; for a distribution of normalized average distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right) filled with constant $h$. The distribution is satisfactory, since it has a lower standard deviation and maximum around $1$. See also the table below for other global measures of regularity for the same cases as those on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right) filled with constant $h$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0416$&lt;br /&gt;
|$0.0344$&lt;br /&gt;
|$0.0832$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.0656$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0508$&lt;br /&gt;
|$0.0418$&lt;br /&gt;
|$0.0849$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.1023$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Computational complexity  of the interior filling algorithm is&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
and when using a uniform-grid based spatial search structure&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; ([http://e6.ijs.si/medusa/docs/html/classmm_1_1KDGrid.html KDGrid] in Medusa) it simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, grid}} = O\left(\frac{|\text{obb} \Omega|}{|\Omega|}N + nN\right),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\text{obb} \Omega$ is the oriented bounding box of $\Omega$.&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling a box with a hole with roughly $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: $1.57$ s, of which $5\%$ is candidate generation, $85\%$ is spatial queries and $4\%$ is spatial inserts&lt;br /&gt;
* 2D, KDGrid: $0.35$ s, of which $19\%$ is candidate generation, $56\%$ is spatial queries and $0.002\%$ is spatial inserts&lt;br /&gt;
* 3D, KDTree: $7.87$ s, of which $6\%$ is candidate generation, $89\%$ is spatial queries and $1\%$ is spatial inserts&lt;br /&gt;
* 3D, KDGrid: $2.58$ s, of which $16\%$ is candidate generation, $70\%$ is spatial queries and $0.001\%$ is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with $N$, with larger $N$ increasing spatial query share by $2$ percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}.&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere and $|S_i| = n$. Now, we can accept candidates that at least $h(\b{r}(\b{\lambda}_i))$ away from $\b{r}(\b{\lambda}_i)$ and enqueue them for expansion. The boundary filling algorithm terminates when the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a part of a unit sphere can be seen in &amp;lt;xr id=&amp;quot;fig:gsf_generation&amp;quot;/&amp;gt; &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the boundary filling algorithm in parametric domain $\Lambda$ (bottom) and main domain $\partial \Omega$ (top). Part of a unit sphere was discretized with $h = 0.08$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, &amp;lt;xr id=&amp;quot;fig:gsf_examples_2&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, for examples of discretized curves in 2D and surfaces in 3D.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_2d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 2D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_simple.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_3d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The boundary filling algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries. &lt;br /&gt;
&lt;br /&gt;
The algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralSurfaceFill.html GeneralSurfaceFill]. See also [[parametric domains]] example and [[NURBS domains]] example.&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt; for a distribution of normalized average distances to $c = 2$ nearest neighbors in 2D on a curve from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; (left) and $c = 3$ nearest neighbors in 3D on a heart-like surface from &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; (right) filled with constant $h$. The distribution is satisfactory, since it has a low standard deviation and maximum around $1$. It is even further improved for bigger $N$ (smaller $h$). See also the table below for other global measures of regularity for the same cases as those on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 2$ nearest neighbors in 2D (left) and $c = 3$ nearest neighbors in 3D (right) filled with constant $h$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0001$&lt;br /&gt;
|$5.1483 \times 10^{-4}$&lt;br /&gt;
|$1.1136 \times 10^{-10}$&lt;br /&gt;
|$0.4622$&lt;br /&gt;
|$0.7808$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0357$&lt;br /&gt;
|$0.0374$&lt;br /&gt;
|$3.8888 \times 10^{-4}$&lt;br /&gt;
|$0.3522$&lt;br /&gt;
|$1.5730$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Since the boundary filling algorithm is based on the interior filling algorithm, its computational complexity is also equal to&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling examples from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; with $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D ($n = 2$): $0.28$ s&lt;br /&gt;
* 3D ($n = 15$): $1.32$ s &lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Relaxation_of_the_nodal_distribution&amp;diff=3075</id>
		<title>Relaxation of the nodal distribution</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Relaxation_of_the_nodal_distribution&amp;diff=3075"/>
				<updated>2020-09-15T10:38:01Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''TODO(Uduh): rewrite''&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated &amp;lt;ref name=&amp;quot;LeeLocal&amp;quot;&amp;gt;Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409.&amp;lt;/ref&amp;gt;, i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes &amp;lt;ref name=&amp;quot;LohnerGeneral&amp;quot;&amp;gt;Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;LiuNode&amp;quot;&amp;gt;Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&amp;lt;/ref&amp;gt;, see [[Positioning of computational nodes]] for our algorithms. Here, an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \b{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;BasicRelax&amp;lt;/code&amp;gt; engine  supports two call types:&lt;br /&gt;
* with supplied distribution function &amp;lt;code&amp;gt;relax(domain, func)&amp;lt;/code&amp;gt;, where it tries to satisfy the user supplied nodal density function &amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with &amp;lt;code&amp;gt;GeneralFill&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;GeneralSurfaceFill&amp;lt;/code&amp;gt;.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing a 2D domain can be found in below code snippet and Figures. Note the difference between relax without supplied distribution (&amp;lt;xr id=&amp;quot;fig:relax_uniform&amp;quot;/&amp;gt;) and with supplied distribution (&amp;lt;xr id=&amp;quot;fig:relax_non-uniform&amp;quot;/&amp;gt;). These examples are extreme, relaxation is usually used to convert an almost desirable node distribution into a desirable node distribution.&lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Define domain shape.&lt;br /&gt;
double r = 0.25;&lt;br /&gt;
BallShape&amp;lt;Vec2d&amp;gt; bs({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
// Fill domain disretization with h.&lt;br /&gt;
auto h = [](Vec2d p){&lt;br /&gt;
    return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
};&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; domain = bs.discretizeBoundaryWithDensity(h);&lt;br /&gt;
GeneralFill&amp;lt;Vec2d&amp;gt; gf;&lt;br /&gt;
gf(domain, h);&lt;br /&gt;
&lt;br /&gt;
// Relax domain to uniform distribution.&lt;br /&gt;
BasicRelax relax;&lt;br /&gt;
relax.iterations(1000).initialHeat(1).finalHeat(0).boundaryProjectionThreshold(0.75)&lt;br /&gt;
     .projectionType(BasicRelax::PROJECT_IN_DIRECTION).numNeighbours(5);&lt;br /&gt;
relax(domain);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:relax_uniform&amp;quot;&amp;gt;&lt;br /&gt;
[[File:relax_uniform.png|thumb|center|800px|&amp;lt;caption&amp;gt; Relaxation of a non-uniform node distribution to a uniform node distribution. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:relax_non-uniform&amp;quot;&amp;gt;&lt;br /&gt;
[[File:relax_non-uniform.png|thumb|center|800px|&amp;lt;caption&amp;gt; Relaxation of a uniform node distribution to a non-uniform node distribution. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Relaxation_of_the_nodal_distribution&amp;diff=3074</id>
		<title>Relaxation of the nodal distribution</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Relaxation_of_the_nodal_distribution&amp;diff=3074"/>
				<updated>2020-09-15T10:37:24Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: Update examples.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''TODO(Uduh): rewrite''&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated &amp;lt;ref name=&amp;quot;LeeLocal&amp;quot;&amp;gt;Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409.&amp;lt;/ref&amp;gt;, i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes &amp;lt;ref name=&amp;quot;LohnerGeneral&amp;quot;&amp;gt;Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;LiuNode&amp;quot;&amp;gt;Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&amp;lt;/ref&amp;gt;, see [[Positioning of computational nodes]] for our algorithms. Here, an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \b{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;BasicRelax&amp;lt;/code&amp;gt; engine  supports two call types:&lt;br /&gt;
* with supplied distribution function &amp;lt;code&amp;gt;relax(domain, func)&amp;lt;/code&amp;gt;, where it tries to satisfy the user supplied nodal density function &amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with &amp;lt;code&amp;gt;GeneralFill&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;GeneralSurfaceFill&amp;lt;/code&amp;gt;.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing a 2D domain can be found in below code snippet and Figures. Note the difference between relax without supplied distribution (&amp;lt;xr id=&amp;quot;fig:relax_uniform&amp;quot;/&amp;gt;) and with supplied distribution (&amp;lt;xr id=&amp;quot;fig:relax_non-uniform&amp;quot;/&amp;gt;). These examples are extreme, relaxation is usually used to convert an almost desirable node distribution into a desirable node distribution.&lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Define domain shape.&lt;br /&gt;
double r = 0.25;&lt;br /&gt;
BallShape&amp;lt;Vec2d&amp;gt; bs({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
// Fill domain disretization with h.&lt;br /&gt;
auto h = [](Vec2d p){&lt;br /&gt;
    return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
};&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; domain = bs.discretizeBoundaryWithDensity(h);&lt;br /&gt;
GeneralFill&amp;lt;Vec2d&amp;gt; gf;&lt;br /&gt;
gf(domain, h);&lt;br /&gt;
&lt;br /&gt;
// Relax domain to uniform distribution.&lt;br /&gt;
BasicRelax relax;&lt;br /&gt;
relax.iterations(1000).initialHeat(1).finalHeat(0).boundaryProjectionThreshold(0.75)&lt;br /&gt;
     .projectionType(BasicRelax::PROJECT_IN_DIRECTION).numNeighbours(5);&lt;br /&gt;
relax(domain);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:relax_uniform&amp;quot;&amp;gt;&lt;br /&gt;
[[File:relax_uniform.png|thumb|center|800px|&amp;lt;caption&amp;gt; Relaxation of non-uniform node distribution to uniform node distribution. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:relax_non-uniform&amp;quot;&amp;gt;&lt;br /&gt;
[[File:relax_non-uniform.png|thumb|center|800px|&amp;lt;caption&amp;gt; Relaxation of niform node distribution to non-uniform node distribution. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Relax_non-uniform.png&amp;diff=3073</id>
		<title>File:Relax non-uniform.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Relax_non-uniform.png&amp;diff=3073"/>
				<updated>2020-09-15T10:34:38Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Relax_uniform.png&amp;diff=3072</id>
		<title>File:Relax uniform.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Relax_uniform.png&amp;diff=3072"/>
				<updated>2020-09-15T10:25:57Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Refinement_of_the_nodal_distribution&amp;diff=3071</id>
		<title>Refinement of the nodal distribution</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Refinement_of_the_nodal_distribution&amp;diff=3071"/>
				<updated>2020-09-15T09:17:17Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
==Problem description==&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==Error indicators==&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
''Warning: this is still a prototype''&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3070</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3070"/>
				<updated>2020-09-15T08:01:49Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithms below. Their goal is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p}): \Omega \to (0, \infty)$, which maps points from $\Omega$ to desired distance to neighboring points.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
Those can also be normalized, getting $r' = r / h$. In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior ==&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of $n$ new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Nearest neighbor search is performed by a spatial search structure, usually a [[K-d tree|''k''-d tree]] is used. Remaining candidates are enqueued and node $\b{p}_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a unit square can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gf_examples_2&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Examples of 2D domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The interior filling algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralFill.html GeneralFill].&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; for a distribution of normalized distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right) filled with constant $h$. It can be seen, that the distribution is satisfactory, since it has a lower standard deviation and maximum around $1$. See also the table below for other global measures of regularity for the same cases as seen on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right) filled with constant $h$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0416$&lt;br /&gt;
|$0.0344$&lt;br /&gt;
|$0.0832$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.0656$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0508$&lt;br /&gt;
|$0.0418$&lt;br /&gt;
|$0.0849$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.1023$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Computational complexity  of the interior filling algorithm is&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
and when using a uniform-grid based spatial search structure&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; ([http://e6.ijs.si/medusa/docs/html/classmm_1_1KDGrid.html KDGrid] in Medusa) it simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, grid}} = O\left(\frac{|\text{obb} \Omega|}{|\Omega|}N + nN\right),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\text{obb} \Omega$ is the oriented bounding box of $\Omega$.&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling a box with a hole with roughly $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: $1.57$ s, of which $5\%$ is candidate generation, $85\%$ is spatial queries and $4\%$ is spatial inserts&lt;br /&gt;
* 2D, KDGrid: $0.35$ s, of which $19\%$ is candidate generation, $56\%$ is spatial queries and $0.002\%$ is spatial inserts&lt;br /&gt;
* 3D, KDTree: $7.87$ s, of which $6\%$ is candidate generation, $89\%$ is spatial queries and $1\%$ is spatial inserts&lt;br /&gt;
* 3D, KDGrid: $2.58$ s, of which $16\%$ is candidate generation, $70\%$ is spatial queries and $0.001\%$ is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with $N$, with larger $N$ increasing spatial query share by $2$ percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}.&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere and $|S_i| = n$. Now, we can accept candidates that at least $h(\b{r}(\b{\lambda}_i))$ away from $\b{r}(\b{\lambda}_i)$ and enqueue them for expansion. The boundary filling algorithm terminates when the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a part of a unit sphere can be seen in &amp;lt;xr id=&amp;quot;fig:gsf_generation&amp;quot;/&amp;gt; &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the boundary filling algorithm in parametric domain $\Lambda$ (bottom) and main domain $\partial \Omega$ (top). Part of a unit sphere was discretized with $h = 0.08$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, &amp;lt;xr id=&amp;quot;fig:gsf_examples_2&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, for examples of discretized curves in 2D and surfaces in 3D.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_2d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 2D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_simple.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_3d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The boundary filling algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries. &lt;br /&gt;
&lt;br /&gt;
The algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralSurfaceFill.html GeneralSurfaceFill]. See also [[parametric domains]] example and [[NURBS domains]] example.&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt; for a distribution of normalized distances to $c = 2$ nearest neighbors in 2D on a curve from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; (left) and $c = 3$ nearest neighbors in 3D on a heart-like surface from &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; (right) filled with constant $h$. It can be seen, that the distribution is satisfactory, since it has a lower standard deviation and maximum around $1$. It is even further improved for bigger $N$ (smaller $h$). See also the table below for other global measures of regularity for the same cases as seen on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 2$ nearest neighbors in 2D (left) and $c = 3$ nearest neighbors in 3D (right) filled with constant $h$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0001$&lt;br /&gt;
|$5.1483 \times 10^{-4}$&lt;br /&gt;
|$1.1136 \times 10^{-10}$&lt;br /&gt;
|$0.4622$&lt;br /&gt;
|$0.7808$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0357$&lt;br /&gt;
|$0.0374$&lt;br /&gt;
|$3.8888 \times 10^{-4}$&lt;br /&gt;
|$0.3522$&lt;br /&gt;
|$1.5730$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Since the boundary filling algorithm is based on the interior filling algorithm, its computational complexity is also equal to&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling examples from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; with $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D ($n = 2$): $0.28$ s&lt;br /&gt;
* 3D ($n = 15$): $1.32$ s &lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Refinement_of_the_nodal_distribution&amp;diff=3069</id>
		<title>Refinement of the nodal distribution</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Refinement_of_the_nodal_distribution&amp;diff=3069"/>
				<updated>2020-09-15T08:01:18Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: Created page with &amp;quot;Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include: * refinem...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
==Problem description==&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==Error indicators==&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Relaxation_of_the_nodal_distribution&amp;diff=3068</id>
		<title>Relaxation of the nodal distribution</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Relaxation_of_the_nodal_distribution&amp;diff=3068"/>
				<updated>2020-09-15T07:59:05Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: Created page with &amp;quot;''TODO(Uduh): rewrite''  To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''TODO(Uduh): rewrite''&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3067</id>
		<title>Medusa</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3067"/>
				<updated>2020-09-15T07:57:50Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--__NOTITLE__--&amp;gt;&lt;br /&gt;
'''Welcome to the Medusa wiki. To visit the main website, go to [http://e6.ijs.si/medusa/ http://e6.ijs.si/medusa/].'''&lt;br /&gt;
&lt;br /&gt;
In [http://e6.ijs.si/ParallelAndDistributedSystems/ Parallel and Distributed Systems Laboratory] we are working on a C++ library that is first and foremost focused on tools for solving Partial Differential Equations by meshless methods. The basic idea is to create generic codes for tools that are needed for solving not only PDEs but many other problems, e.g. Moving Least Squares approximation, $k$-d tree, domain generation engines, etc.&lt;br /&gt;
We call this open source meshless project [http://e6.ijs.si/medusa/ Medusa: Coordinate Free Meshless Method implementation (MM)].&lt;br /&gt;
&lt;br /&gt;
Technical details about code and examples  can be found on our [http://e6.ijs.si/medusa/docs/ documentation page] and [https://gitlab.com/e62Lab/medusa Gitlab repository]. [[File:C.png|100px||link=https://gitlab.com/e62Lab/medusa|alt=Alt text|code]] [[File:doxygen.png|100px|link=http://e6.ijs.si/medusa/docs/|alt=Alt text|Documentation page]]&lt;br /&gt;
&lt;br /&gt;
This wiki site is meant for more relaxed discussions about general principles, possible and already implemented applications, preliminary analyses, etc.&lt;br /&gt;
Note, that there are many grammatical mistakes, typos, stupid sentences, etc. This wiki is meant for quick information exchange and therefore we do not invest a lot of energy into styling :).  &lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
* [https://gitlab.com/e62Lab/medusa Code on Gitlab]&lt;br /&gt;
* [[How to build | Installation and building]]&lt;br /&gt;
* [[Including this library in your project | Including this library in your project]]&lt;br /&gt;
* [[Testing | Running tests]]&lt;br /&gt;
* [http://e6.ijs.si/medusa/docs/ Technical documentation]&lt;br /&gt;
* [[Coding style | Coding style]]&lt;br /&gt;
* [[Wiki editing guide | Wiki editing and backup guide]]&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
In this section we present exact examples. Each of the below solutions can be found also in in the repository under examples. More explanation about the physical background and solution procedure can be found in following sections.&lt;br /&gt;
* [[Philosophy of examples and how to run them]]&lt;br /&gt;
* [[Poisson's equation]]&lt;br /&gt;
* [[Heat equation]]&lt;br /&gt;
* [[Linear elasticity]]&lt;br /&gt;
* [[Complex-valued problems]]&lt;br /&gt;
* [[Coupled domains]]&lt;br /&gt;
* [[Parametric domains | Parametric domains &amp;amp;ndash; Curved surface with variable density]]&lt;br /&gt;
* [[NURBS domains | Domains modeled with non-uniform rational basis spline's (NURBS)]]&lt;br /&gt;
* [[Customization]]&lt;br /&gt;
* [[Ghost nodes]]&lt;br /&gt;
* [[Electromagnetic scattering]]&lt;br /&gt;
* [[Schrödinger equation]]&lt;br /&gt;
* [[Wave equation]]&lt;br /&gt;
* [[Cahn-Hilliard equation]]&lt;br /&gt;
* [[Meshless Lattice Boltzmann method]]&lt;br /&gt;
&lt;br /&gt;
== Building blocks ==&lt;br /&gt;
Medusa is modular coordinate-free parallel implementation of a numerical framework designed, but not limited to, for solving PDEs. In this section we present main modules of the library that can be also used as a standalone tools. &lt;br /&gt;
* [[Positioning of computational nodes]] &lt;br /&gt;
* [[Relaxation of the nodal distribution]]&lt;br /&gt;
* [[Refinement of the nodal distribution]]&lt;br /&gt;
* [[k-d tree|''k''-d tree]] and other spatial search structures&lt;br /&gt;
* Solving [[Solving linear systems | linear systems]], [[Solving overdetermined systems | overdetermined]] and [[Solving underdetermined systems | underdetermined]]&lt;br /&gt;
* [[Weighted Least Squares (WLS)]]&lt;br /&gt;
* [[Computation of shape functions]]&lt;br /&gt;
* [[Meshless Local Strong Form Method (MLSM)]]&lt;br /&gt;
* [[Radial basis function-generated finite differences (RBF-FD)]]&lt;br /&gt;
* [[Ghost nodes (theory)]]&lt;br /&gt;
* [[Integrators for time stepping]]&lt;br /&gt;
* [[RBF Interpolation]]&lt;br /&gt;
&lt;br /&gt;
== Discussions / Applications ==&lt;br /&gt;
This section is meant for general discussion about the physical background of the examples, the solution procedures, various applications, etc. Note, that code snippets presented in discussion might not reflect the actual state of Medusa.  &lt;br /&gt;
* Basic PDE solutions&lt;br /&gt;
** [[Convection Diffusion equation | Convection Diffusion equation]]&lt;br /&gt;
**[[Wave equation application]] &lt;br /&gt;
* [[Adaptivity]]&lt;br /&gt;
* [[Solid Mechanics]]&lt;br /&gt;
** [[Point contact]]&lt;br /&gt;
** [[Hertzian contact]]&lt;br /&gt;
** [[Cantilever beam]]&lt;br /&gt;
** [[Fretting fatigue case]]&lt;br /&gt;
* [[Fluid Mechanics]]&lt;br /&gt;
** [[Lid driven cavity]]&lt;br /&gt;
** [[de Vahl Davis natural convection test]]&lt;br /&gt;
** [[Natural convection in 3D irregular domain]]&lt;br /&gt;
** [[Natural convection from heated cylinder]]&lt;br /&gt;
** [[Natural convection between concentric cylinders]]&lt;br /&gt;
* [[Computational electromagnetics]]&lt;br /&gt;
** [[Triple dielectric step in 1D]]&lt;br /&gt;
** [[Scattering from an infinite cylinder]]&lt;br /&gt;
** [[Point source near an anisotropic lens]]&lt;br /&gt;
* Other applications&lt;br /&gt;
** [[Attenuation due to liquid water content in the atmosphere|Attenuation of a satellite communication]]&lt;br /&gt;
** [[Heart rate variability detection]]&lt;br /&gt;
** [[Bioheat equation]]&lt;br /&gt;
&lt;br /&gt;
== Performance analyses ==&lt;br /&gt;
* [[Execution on Intel® Xeon Phi™ co-processor]]&lt;br /&gt;
* [[1D MLSM and FDM comparison]]&lt;br /&gt;
* [[:File:tech_report.pdf|Execution overheads due to clumsy types::technical report]] [[File:pdf-file.gif]]&lt;br /&gt;
* [[Solving sparse systems]]&lt;br /&gt;
* [[Eigen paralelization]]&lt;br /&gt;
&lt;br /&gt;
== Last changes ==&lt;br /&gt;
&amp;lt;news unique=1 limit = 5&amp;gt;&lt;br /&gt;
*{{{timeanddate}}} :: {{{title}}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/news&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous ==&lt;br /&gt;
* FAQ  - [[Frequently asked questions]]. &lt;br /&gt;
* [[List of wiki contributors]]&lt;br /&gt;
* List of library contributors: [http://e6.ijs.si/medusa/about#about-contributors See the official website]&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
* Slak J., Kosec G. Adaptive radial basis function-generated finite differences method for contact problems. International journal for numerical methods in engineering, ISSN 0029-5981 [http://www-e6.ijs.si/ParallelAndDistributedSystems/pdf/32230439.pdf manuscript]&lt;br /&gt;
* Slak J., Kosec G.; Refined meshless local strong form solution of Cauchy-Navier equation on an irregular domain. Engineering analysis with boundary elements. 2018;11 ; [http://comms.ijs.si/~gkosec/data/papers/31107623.pdf manuscript]&lt;br /&gt;
* Depolli, M., Kosec, G., Assessment of differential evolution for multi-objective optimization in a natural convection problem solved by a local meshless method. Engineering optimization, 2017, vol. 49, no. 4, pp. 675-692 ;[http://comms.ijs.si/~gkosec/data/papers/29639719.pdf manuscript]&lt;br /&gt;
* Kosec G., A local numerical solution of a fluid-flow problem on an irregular domain. Advances in engineering software. 2016;7 ; [29512743] ; [http://comms.ijs.si/~gkosec/data/papers/29512743.pdf manuscript]&lt;br /&gt;
* Kosec G., Trobec R., Simulation of semiconductor devices with a local numerical approach. Engineering analysis with boundary elements. 2015;69-75; [27912487] ; [http://comms.ijs.si/~gkosec/data/papers/27912487.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., Simulation of macrosegregation with mesosegregates in binary metallic casts by a meshless method. Engineering analysis with boundary elements. 2014;36-44; [http://comms.ijs.si/~gkosec/data/papers/3218939.pdf manuscript]&lt;br /&gt;
* Kosec G., Depolli M., Rashkovska A., Trobec R., Super linear speedup in a local parallel meshless solution of thermo-fluid problem. Computers &amp;amp; Structures. 2014;133:30-38; [http://comms.ijs.si/~gkosec/data/papers/27339815.pdf manuscript]&lt;br /&gt;
* Kosec G., Zinterhof P., Local strong form meshless method on multiple Graphics Processing Units. Computer modeling in engineering &amp;amp; sciences. 2013;91:377-396; [http://comms.ijs.si/~gkosec/data/papers/26785063.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., H-adaptive local radial basis function collocation meshless method. Computers, materials &amp;amp; continua. 2011;26:227-253; [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerBurgers.pdf manuscript]&lt;br /&gt;
* Trobec R., Kosec G., Šterk M., Šarler B., Comparison of local weak and strong form meshless methods for 2-D diffusion equation. Engineering analysis with boundary elements. 2012;36:310-321; [http://comms.ijs.si/~gkosec/data/papers/EABE2499.pdf manuscript]&lt;br /&gt;
* Kosec G, Zaloznik M, Sarler B, Combeau H. A Meshless Approach Towards Solution of Macrosegregation Phenomena. CMC: Computers, Materials, &amp;amp; Continua. 2011;580:1-27 [http://comms.ijs.si/~gkosec/data/papers/KosecZaloznikSarlerCombeauSegregation.pdf manuscript]&lt;br /&gt;
* Kosec G, Sarler B. Solution of thermo-fluid problems by collocation with local pressure correction. International Journal of Numerical Methods for Heat &amp;amp; Fluid Flow. 2008;18:868-82 [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerNS2008.pdf manuscript]&lt;br /&gt;
*  Trobec R., Kosec G., Parallel Scientific Computing, ISBN: 978-3-319-17072-5 (Print) 978-3-319-17073-2.&lt;br /&gt;
*  Slak, J., Kosec, G.. Detection of heart rate variability from a wearable differential ECG device., MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938, pp 450-455.&lt;br /&gt;
*  Kolman, M., Kosec, G. Correlation between attenuation of 20 GHz satellite communication link and liquid water content in the atmosphere. MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938. pp. 308-313.&lt;br /&gt;
&lt;br /&gt;
==Related pages==&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/#!NumericalMethods&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/#!utils&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/#!NUMA&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3066</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3066"/>
				<updated>2020-09-14T13:39:08Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The goal of the first two algorithms is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p})$. The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
Those can also be normalized, getting $r' = r / h$. In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior ==&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of $n$ new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Nearest neighbor search is performed by a spatial search structure, usually a [[K-d tree|''k''-d tree]] is used. Remaining candidates are enqueued and node $\b{p}_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a unit square can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gf_examples_2&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Examples of 2D domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The interior filling algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralFill.html GeneralFill].&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; for a distribution of normalized distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right) filled with constant $h$. It can be seen, that the distribution is satisfactory, since it has a lower standard deviation and maximum around $1$. See also the table below for other global measures of regularity for the same cases as seen on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right) filled with constant $h$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0416$&lt;br /&gt;
|$0.0344$&lt;br /&gt;
|$0.0832$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.0656$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0508$&lt;br /&gt;
|$0.0418$&lt;br /&gt;
|$0.0849$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.1023$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Computational complexity  of the interior filling algorithm is&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
and when using a uniform-grid based spatial search structure&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; ([http://e6.ijs.si/medusa/docs/html/classmm_1_1KDGrid.html KDGrid] in Medusa) it simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, grid}} = O\left(\frac{|\text{obb} \Omega|}{|\Omega|}N + nN\right),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\text{obb} \Omega$ is the oriented bounding box of $\Omega$.&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling a box with a hole with roughly $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: $1.57$ s, of which $5\%$ is candidate generation, $85\%$ is spatial queries and $4\%$ is spatial inserts&lt;br /&gt;
* 2D, KDGrid: $0.35$ s, of which $19\%$ is candidate generation, $56\%$ is spatial queries and $0.002\%$ is spatial inserts&lt;br /&gt;
* 3D, KDTree: $7.87$ s, of which $6\%$ is candidate generation, $89\%$ is spatial queries and $1\%$ is spatial inserts&lt;br /&gt;
* 3D, KDGrid: $2.58$ s, of which $16\%$ is candidate generation, $70\%$ is spatial queries and $0.001\%$ is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with $N$, with larger $N$ increasing spatial query share by $2$ percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}.&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere and $|S_i| = n$. Now, we can accept candidates that at least $h(\b{r}(\b{\lambda}_i))$ away from $\b{r}(\b{\lambda}_i)$ and enqueue them for expansion. The boundary filling algorithm terminates when the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a part of a unit sphere can be seen in &amp;lt;xr id=&amp;quot;fig:gsf_generation&amp;quot;/&amp;gt; &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the boundary filling algorithm in parametric domain $\Lambda$ (bottom) and main domain $\partial \Omega$ (top). Part of a unit sphere was discretized with $h = 0.08$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, &amp;lt;xr id=&amp;quot;fig:gsf_examples_2&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, for examples of discretized curves in 2D and surfaces in 3D.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_2d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 2D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_simple.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_3d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The boundary filling algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries. &lt;br /&gt;
&lt;br /&gt;
The algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralSurfaceFill.html GeneralSurfaceFill]. See also [[parametric domains]] example and [[NURBS domains]] example.&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt; for a distribution of normalized distances to $c = 2$ nearest neighbors in 2D on a curve from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; (left) and $c = 3$ nearest neighbors in 3D on a heart-like surface from &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; (right) filled with constant $h$. It can be seen, that the distribution is satisfactory, since it has a lower standard deviation and maximum around $1$. It is even further improved for bigger $N$ (smaller $h$). See also the table below for other global measures of regularity for the same cases as seen on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 2$ nearest neighbors in 2D (left) and $c = 3$ nearest neighbors in 3D (right) filled with constant $h$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0001$&lt;br /&gt;
|$5.1483 \times 10^{-4}$&lt;br /&gt;
|$1.1136 \times 10^{-10}$&lt;br /&gt;
|$0.4622$&lt;br /&gt;
|$0.7808$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0357$&lt;br /&gt;
|$0.0374$&lt;br /&gt;
|$3.8888 \times 10^{-4}$&lt;br /&gt;
|$0.3522$&lt;br /&gt;
|$1.5730$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Since the boundary filling algorithm is based on the interior filling algorithm, its computational complexity is also equal to&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling examples from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; with $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D ($n = 2$): $0.28$ s&lt;br /&gt;
* 3D ($n = 15$): $1.32$ s &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
''TODO(Uduh): rewrite''&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3065</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3065"/>
				<updated>2020-09-14T13:37:06Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: GF and GSF rewrite&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The goal of the first two algorithms is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p})$. The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
Those can also be normalized, getting $r' = r / h$. In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior ==&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of $n$ new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Nearest neighbor search is performed by a spatial search structure, usually a [[K-d tree|''k''-d tree]] is used. Remaining candidates are enqueued and node $\b{p}_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a unit square can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gf_examples_2&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Examples of 2D domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The interior filling algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralFill.html GeneralFill].&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; for a distribution of normalized distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right). It can be seen, that the distribution is satisfactory, since it has a lower standard deviation and maximum around $1$. See also the table below for other global measures of regularity for the same cases as seen on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 3$ nearest neighbors on a 2D unit square (left) and $c = 6$ nearest neighbors on a 3D unit cube (right) &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0416$&lt;br /&gt;
|$0.0344$&lt;br /&gt;
|$0.0832$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.0656$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0508$&lt;br /&gt;
|$0.0418$&lt;br /&gt;
|$0.0849$&lt;br /&gt;
|$0.5000$&lt;br /&gt;
|$2.1023$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Computational complexity  of the interior filling algorithm is&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
and when using a uniform-grid based spatial search structure&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; ([http://e6.ijs.si/medusa/docs/html/classmm_1_1KDGrid.html KDGrid] in Medusa) it simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, grid}} = O\left(\frac{|\text{obb} \Omega|}{|\Omega|}N + nN\right),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\text{obb} \Omega$ is the oriented bounding box of $\Omega$.&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling a box with a hole with roughly $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: $1.57$ s, of which $5\%$ is candidate generation, $85\%$ is spatial queries and $4\%$ is spatial inserts&lt;br /&gt;
* 2D, KDGrid: $0.35$ s, of which $19\%$ is candidate generation, $56\%$ is spatial queries and $0.002\%$ is spatial inserts&lt;br /&gt;
* 3D, KDTree: $7.87$ s, of which $6\%$ is candidate generation, $89\%$ is spatial queries and $1\%$ is spatial inserts&lt;br /&gt;
* 3D, KDGrid: $2.58$ s, of which $16\%$ is candidate generation, $70\%$ is spatial queries and $0.001\%$ is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with $N$, with larger $N$ increasing spatial query share by $2$ percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}.&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere and $|S_i| = n$. Now, we can accept candidates that at least $h(\b{r}(\b{\lambda}_i))$ away from $\b{r}(\b{\lambda}_i)$ and enqueue them for expansion. The boundary filling algorithm terminates when the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a part of a unit sphere can be seen in &amp;lt;xr id=&amp;quot;fig:gsf_generation&amp;quot;/&amp;gt; &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the boundary filling algorithm in parametric domain $\Lambda$ (bottom) and main domain $\partial \Omega$ (top). Part of a unit sphere was discretized with $h = 0.08$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, &amp;lt;xr id=&amp;quot;fig:gsf_examples_2&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;, for examples of discretized curves in 2D and surfaces in 3D.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_2d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 2D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_simple.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_3d_article.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The boundary filling algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries. &lt;br /&gt;
&lt;br /&gt;
The algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralSurfaceFill.html GeneralSurfaceFill]. See also [[parametric domains]] example and [[NURBS domains]] example.&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_hist&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt; for a distribution of normalized distances to $c = 2$ nearest neighbors in 2D on a curve from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; (left) and $c = 3$ nearest neighbors in 3D on a heart-like surface from &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; (right). It can be seen, that the distribution is satisfactory, since it has a lower standard deviation and maximum around $1$. It is even further improved for bigger $N$ (smaller $h$). See also the table below for other global measures of regularity for the same cases as seen on the histograms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_hist&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_hist.png|thumb|center|600px|&amp;lt;caption&amp;gt; Distribution of normalized distances to $c = 2$ nearest neighbors in 2D (left) and $c = 3$ nearest neighbors in 3D (right). &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto; border: none;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|Measures of regularity&lt;br /&gt;
|-&lt;br /&gt;
|dim.&lt;br /&gt;
|$\text{mean} \, \bar{d}'_i$&lt;br /&gt;
|$\text{std} \, \bar{d}'_i$&lt;br /&gt;
|$\text{mean} \left(\left(d_i^{\text{max}}\right)' - \left(d_i^{\text{min}}\right)'\right)$&lt;br /&gt;
|$r'_\min$&lt;br /&gt;
|$r'_\max$&lt;br /&gt;
|-&lt;br /&gt;
|2D&lt;br /&gt;
|$1.0001$&lt;br /&gt;
|$5.1483 \times 10^{-4}$&lt;br /&gt;
|$1.1136 \times 10^{-10}$&lt;br /&gt;
|$0.4622$&lt;br /&gt;
|$0.7808$&lt;br /&gt;
|-&lt;br /&gt;
|3D&lt;br /&gt;
|$1.0357$&lt;br /&gt;
|$0.0374$&lt;br /&gt;
|$3.8888 \times 10^{-4}$&lt;br /&gt;
|$0.3522$&lt;br /&gt;
|$1.5730$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Since the boundary filling algorithm is based on the interior filling algorithm, its computational complexity is also equal to&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling examples from &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; with $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D ($n = 2$): $0.28$ s&lt;br /&gt;
* 3D ($n = 15$): $1.32$ s &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
''TODO(Uduh): rewrite''&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Gf_hist.png&amp;diff=3064</id>
		<title>File:Gf hist.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Gf_hist.png&amp;diff=3064"/>
				<updated>2020-09-14T13:27:13Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_hist.png&amp;diff=3063</id>
		<title>File:Gsf hist.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_hist.png&amp;diff=3063"/>
				<updated>2020-09-14T11:13:48Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_hist_3d.png&amp;diff=3061</id>
		<title>File:Gsf hist 3d.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_hist_3d.png&amp;diff=3061"/>
				<updated>2020-09-14T11:05:53Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_hist_2d.png&amp;diff=3062</id>
		<title>File:Gsf hist 2d.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_hist_2d.png&amp;diff=3062"/>
				<updated>2020-09-14T11:05:53Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_3d_article.png&amp;diff=3059</id>
		<title>File:Gsf 3d article.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_3d_article.png&amp;diff=3059"/>
				<updated>2020-09-14T10:51:41Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_2d_article.png&amp;diff=3060</id>
		<title>File:Gsf 2d article.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_2d_article.png&amp;diff=3060"/>
				<updated>2020-09-14T10:51:41Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3058</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3058"/>
				<updated>2020-09-11T19:48:41Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The goal of the first two algorithms is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p})$. The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior ==&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of $n$ new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Nearest neighbor search is performed by a spatial search structure, usually a [[K-d tree|''k''-d tree]] is used. Remaining candidates are enqueued and node $\b{p}_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a unit square can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gf_examples_2&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Examples of 2D domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The interior filling algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralFill.html GeneralFill].&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) histograms and table''&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Computational complexity  of the interior filling algorithm is&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, tree}} = O(nN \log N)&lt;br /&gt;
\end{equation}&lt;br /&gt;
and when using a uniform-grid based spatial search structure&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; ([http://e6.ijs.si/medusa/docs/html/classmm_1_1KDGrid.html KDGrid] in Medusa) it simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, grid}} = O\left(\frac{|\text{obb} \Omega|}{|\Omega|}N + nN\right),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\text{obb} \Omega$ is the oriented bounding box of $\Omega$.&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling a box with a hole with roughly $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: $1.57$ s, of which $5\%$ is candidate generation, $85\%$ is spatial queries and $4\%$ is spatial inserts&lt;br /&gt;
* 2D, KDGrid: $0.35$ s, of which $19\%$ is candidate generation, $56\%$ is spatial queries and $0.002\%$ is spatial inserts&lt;br /&gt;
* 3D, KDTree: $7.87$ s, of which $6\%$ is candidate generation, $89\%$ is spatial queries and $1\%$ is spatial inserts&lt;br /&gt;
* 3D, KDGrid: $2.58$ s, of which $16\%$ is candidate generation, $70\%$ is spatial queries and $0.001\%$ is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with $N$, with larger $N$ increasing spatial query share by $2$ percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere and $|S_i| = n$. Now, we can accept candidates that at least $h(\b{r}(\b{\lambda}_i))$ away from $\b{r}(\b{\lambda}_i)$ and enqueue them for expansion. The boundary filling algorithm terminates when the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a part of a unit sphere can be seen in &amp;lt;xr id=&amp;quot;fig:gsf_generation&amp;quot;/&amp;gt; &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the boundary filling algorithm in parametric domain $\Lambda$ (bottom) and main domain $\partial \Omega$ (top). Part of a unit sphere was discretized with $h = 0.08$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt;, &amp;lt;xr id=&amp;quot;fig:gsf_examples_2&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; for examples of discretized curves in 2D and surfaces in 3D.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_simp.png|thumb|&amp;lt;caption&amp;gt; Example of a 2D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_simple.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_complex.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The boundary filling algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries. &lt;br /&gt;
&lt;br /&gt;
The algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralSurfaceFill.html GeneralSurfaceFill].&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) examples from article, histograms and table''&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Since the boundary filling algorithm is based on the interior filling algorithm, its computational complexity is also equal to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) example computational times''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
''TODO(Uduh): rewrite''&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3057</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3057"/>
				<updated>2020-09-11T13:36:50Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The goal of the first two algorithms is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p})$. The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior ==&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of $n$ new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Nearest neighbor search is performed by a spatial search structure, usually a [[K-d tree|''k''-d tree]] is used. Remaining candidates are enqueued and node $\b{p}_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a unit square can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gf_examples_2&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Examples of 2D domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The interior filling algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralFill.html GeneralFill].&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) histograms and table''&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Computational complexity  of the interior filling algorithm is&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, tree}} = O(nN \log N)&lt;br /&gt;
\end{equation}&lt;br /&gt;
and when using a uniform-grid based spatial search structure&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; ([http://e6.ijs.si/medusa/docs/html/classmm_1_1KDGrid.html KDGrid] in Medusa) it simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, grid}} = O\left(\frac{|\text{obb} \Omega|}{|\Omega|}N + nN\right),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\text{obb} \Omega$ is the oriented bounding box of $\Omega$.&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer of filling a box with a hole with roughly $100 \, 000$ nodes, given as a rough reference.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: $1.57$ s, of which $5\%$ is candidate generation, $85\%$ is spatial queries and $4\%$ is spatial inserts&lt;br /&gt;
* 2D, KDGrid: $0.35$ s, of which $19\%$ is candidate generation, $56\%$ is spatial queries and $0.002\%$ is spatial inserts&lt;br /&gt;
* 3D, KDTree: $7.87$ s, of which $6\%$ is candidate generation, $89\%$ is spatial queries and $1\%$ is spatial inserts&lt;br /&gt;
* 3D, KDGrid: $2.58$ s, of which $16\%$ is candidate generation, $70\%$ is spatial queries and $0.001\%$ is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with $N$, with larger $N$ increasing spatial query share by $2$ percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere and $|S_i| = n$. Now, we can accept candidates that at least $h(\b{r}(\b{\lambda}_i))$ away from $\b{r}(\b{\lambda}_i)$ and enqueue them for expansion. The boundary filling algorithm terminates when the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a part of a unit sphere can be seen in &amp;lt;xr id=&amp;quot;fig:gsf_generation&amp;quot;/&amp;gt; &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the boundary filling algorithm on a part of a unit sphere. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt;, &amp;lt;xr id=&amp;quot;fig:gsf_examples_2&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; for examples of discretized curves in 2D and surfaces in 3D.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_simp.png|thumb|&amp;lt;caption&amp;gt; Example of a 2D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_simple.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_complex.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The boundary filling algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries. &lt;br /&gt;
&lt;br /&gt;
The algorithm is thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralSurfaceFill.html GeneralSurfaceFill].&lt;br /&gt;
&lt;br /&gt;
=== Regularity analysis ===&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) examples from article, histograms and table''&lt;br /&gt;
&lt;br /&gt;
=== Computational complexity ===&lt;br /&gt;
&lt;br /&gt;
Since the boundary filling algorithm is based on the interior filling algorithm, its computational complexity is also equal to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary}} = O(P(N) + NnQ(N)+NI(N)),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] spatial search structure this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{boundary, tree}} = O(nN \log N).&lt;br /&gt;
\end{equation}&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) example computational times''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
''TODO(Uduh): rewrite''&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3056</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3056"/>
				<updated>2020-09-11T13:00:44Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The goal of the first two algorithms is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p})$. The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior with nodes ==&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of $n$ new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Nearest neighbor search is performed by a spatial search structure, usually a [[K-d tree|''k''-d tree]] is used. Remaining candidates are enqueued and node $\b{p}_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a unit square can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gf_examples_2&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Examples of 2D domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) histograms and table''&lt;br /&gt;
&lt;br /&gt;
Computational complexity  of the interior filling algorithm is&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior}} = O(P(N) + Nn(Q(N)+I(N))),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation computational complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, tree}} = O(nN \log N)&lt;br /&gt;
\end{equation}&lt;br /&gt;
and when using a uniform-grid based spatial search structure&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; ([http://e6.ijs.si/medusa/docs/html/classmm_1_1KDGrid.html KDGrid] in Medusa) it simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, grid}} = O\left(\frac{|\text{obb} \Omega|}{|\Omega|}N + nN\right),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\text{obb} \Omega$ is the oriented bounding box of $\Omega$.&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer, given as a rough reference, of filling a box with a hole with roughly $100 \, 000$ nodes.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: $1.57$ s, of which $5\%$ is candidate generation, $85\%$ is spatial queries and $4\%$ is spatial inserts&lt;br /&gt;
* 2D, KDGrid: $0.35$ s, of which $19\%$ is candidate generation, $56\%$ is spatial queries and $0.002\%$ is spatial inserts&lt;br /&gt;
* 3D, KDTree: $7.87$ s, of which $6\%$ is candidate generation, $89\%$ is spatial queries and $1\%$ is spatial inserts&lt;br /&gt;
* 3D, KDGrid: $2.58$ s, of which $16\%$ is candidate generation, $70\%$ is spatial queries and $0.001\%$ is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with $N$, with larger $N$ increasing spatial query share by $2$ percent points.&lt;br /&gt;
&lt;br /&gt;
The interior filling algorithm is more thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralFill.html GeneralFill].&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere and $|S_i| = n$. Now, we can accept candidates that at least $h(\b{r}(\b{\lambda}_i))$ away from $\b{r}(\b{\lambda}_i)$ and enqueue them for expansion. The boundary filling algorithm terminates when the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress on a part of a unit sphere can be seen in &amp;lt;xr id=&amp;quot;fig:gsf_generation&amp;quot;/&amp;gt; &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gsf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gsf_examples_1&amp;quot;/&amp;gt;, &amp;lt;xr id=&amp;quot;fig:gsf_examples_2&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gsf_examples_3&amp;quot;/&amp;gt; for examples of discretized curves in 2D and surfaces in 3D.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_simp.png|thumb|&amp;lt;caption&amp;gt; Example of a 2D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_simple.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gsf_examples_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_complex.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the boundary filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) histograms and table''&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) computational complexity''&lt;br /&gt;
&lt;br /&gt;
The boundary filling algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries. This algorithm is more thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;/&amp;gt;. It is implemented in Medusa as [http://e6.ijs.si/medusa/docs/html/classmm_1_1GeneralSurfaceFill.html GeneralSurfaceFill].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
''TODO(Uduh): rewrite''&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_generation.png&amp;diff=3055</id>
		<title>File:Gsf generation.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Gsf_generation.png&amp;diff=3055"/>
				<updated>2020-09-11T12:58:48Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3054</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3054"/>
				<updated>2020-09-11T12:40:08Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The goal of the first two algorithms is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p})$. The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior with nodes ==&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of $n$ new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Nearest neighbor search is performed by a spatial search structure, usually a [[K-d tree|''k''-d tree]] is used. Remaining candidates are enqueued and node $\b{p}_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples_1&amp;quot;/&amp;gt; and &amp;lt;xr id=&amp;quot;fig:gf_examples_2&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Examples of 2D domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:3d_poisson_disk_sampling.png|thumb|&amp;lt;caption&amp;gt; Example of a 3D domain filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''TODO(Uduh) histograms and table''&lt;br /&gt;
&lt;br /&gt;
Computational complexity  of the interior filling algorithm is&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior}} = O(P(N) + Nn(Q(N)+I(N))),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of generated nodes, $P$ is the precomputation computational complexity of the spatial search structure, $Q$ is the computational complexity of a radius (nearest neighbor) query and $I$ is the computational complexity of insertions into the spatial search structure. When using a [[K-d tree|''k''-d tree]] this simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, tree}} = O(nN \log N)&lt;br /&gt;
\end{equation}&lt;br /&gt;
and when using a uniform-grid based spatial search structure&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt; ([http://e6.ijs.si/medusa/docs/html/classmm_1_1KDGrid.html KDGrid] in Medusa) it simplifies to&lt;br /&gt;
\begin{equation}&lt;br /&gt;
T_{\text{interior, grid}} = O\left(\frac{|\text{obb} \Omega|}{|\Omega|}N + nN\right),&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\text{obb} \Omega$ is the oriented bounding box of $\Omega$.&lt;br /&gt;
&lt;br /&gt;
Below are some computational times on a laptop computer, given as a rough reference, of filling a box with a hole with roughly $100 \, 000$ nodes.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: $1.57$ s, of which $5\%$ is candidate generation, $85\%$ is spatial queries and $4\%$ is spatial inserts&lt;br /&gt;
* 2D, KDGrid: $0.35$ s, of which $19\%$ is candidate generation, $56\%$ is spatial queries and $0.002\%$ is spatial inserts&lt;br /&gt;
* 3D, KDTree: $7.87$ s, of which $6\%$ is candidate generation, $89\%$ is spatial queries and $1\%$ is spatial inserts&lt;br /&gt;
* 3D, KDGrid: $2.58$ s, of which $16\%$ is candidate generation, $70\%$ is spatial queries and $0.001\%$ is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with $N$, with larger $N$ increasing spatial query share by $2$ percent points.&lt;br /&gt;
&lt;br /&gt;
This algorithm is more thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
''TODO(Uduh): rewrite''&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere.&lt;br /&gt;
&lt;br /&gt;
Here are some examples of curves and surfaces filled with the described algorithm.&lt;br /&gt;
&lt;br /&gt;
[[File:2d_simp.png|400px]] [[File:3d_complex.png|400px]] [[File:3d_simple.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The described algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries.&lt;br /&gt;
&lt;br /&gt;
This algorithm is more thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
''TODO(Uduh): rewrite''&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3053</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3053"/>
				<updated>2020-09-11T11:41:18Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The goal of the first two algorithms is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p})$. The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with:&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;:&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
In practice, the maximum empty sphere radius can be numerically estimated by discretizing $\Omega$ with a much smaller nodal spacing $h$ and calculating the maximum empty sphere radius with center in one of the generated nodes.&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior with nodes ==&lt;br /&gt;
TODO(Uduh): rewrite&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $\b{p}_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(\b{p}_i)$. A&lt;br /&gt;
set $C_i$ of new candidates is generated, which lie on the sphere with center $\b{p}_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Remaining candidates are enqueued and node $p_i$ is marked as &amp;quot;expanded&amp;quot;.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
An illustration of the algorithm's progress can be seen in &amp;lt;xr id=&amp;quot;fig:gf_generation&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations, SIAM Journal on Scientific Computing, 41 (2019), &lt;br /&gt;
pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_generation&amp;quot;&amp;gt;&lt;br /&gt;
[[File:gf_generation.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Progress of the interior filling algorithm on a unit square. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;lt;xr id=&amp;quot;fig:gf_examples&amp;quot;/&amp;gt; for examples of discretized 2D and 3D domains.&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:gf_examples&amp;quot;&amp;gt;&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png]] [[File:3d_poisson_disk_sampling.png]]&amp;lt;caption&amp;gt; Some examples of domains filled by the interior filling algorithm. &amp;lt;/caption&amp;gt;&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Computational times on a laptop computer, given as a rough reference. Filling a box with a hole with roughly 100 000 nodes.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: 1.57 s, of which 5% is candidate generation, 85% is spatial queries and 4% is spatial inserts&lt;br /&gt;
* 2D, KDGrid: 0.35 s, of which 19% is candidate generation, 56% is spatial queries and 0.002% is spatial inserts&lt;br /&gt;
* 3D, KDTree: 7.87 s, of which 6% is candidate generation, 89% is spatial queries and 1% is spatial inserts&lt;br /&gt;
* 3D, KDGrid: 2.58 s, of which 16% is candidate generation, 70% is spatial queries and 0.001% is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with N, with larger N increasing spatial query share by 2 percent points.&lt;br /&gt;
&lt;br /&gt;
This algorithm is more thoroughly analyzed in &amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
TODO(Uduh): rewrite&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere.&lt;br /&gt;
&lt;br /&gt;
Here are some examples of curves and surfaces filled with the described algorithm.&lt;br /&gt;
&lt;br /&gt;
[[File:2d_simp.png|400px]] [[File:3d_complex.png|400px]] [[File:3d_simple.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The described algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries.&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
TODO(Uduh): rewrite&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:Gf_generation.png&amp;diff=3052</id>
		<title>File:Gf generation.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:Gf_generation.png&amp;diff=3052"/>
				<updated>2020-09-11T11:27:33Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3051</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3051"/>
				<updated>2020-09-11T11:08:54Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The goal of the first two algorithms is to fill an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(\b{p})$. The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Measures of node regularity ==&lt;br /&gt;
&lt;br /&gt;
To analyze the regularity of nodes locally, we find $c$ nearest neighbors $\b{p}_{i, j}, j = 1, 2, \dots c$ of each node $\b{p}_i$. Local regularity can now be measured with:&lt;br /&gt;
\begin{align*}&lt;br /&gt;
\bar{d}_i = \frac{1}{c} \sum_{j =1}^{c}\|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{average distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{min}} = \min_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{minimum distance to} \ c \ \text{nearest neighbors}, \\&lt;br /&gt;
d_i^{\text{max}} = \max_{j=1, \dots c} \|\b{p}_i - \b{p}_{i, j}\| &amp;amp; \quad \dots \quad \text{maximum distance to} \ c \ \text{nearest neighbors}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
We can also normalize the quantities by scaling them with $h$, thus getting $d'_i = d_i / h(\b{p}_i)$. &lt;br /&gt;
&lt;br /&gt;
Global regularity can be assessed by plotting distributions of local regularity measures. If $h$ is a constant function, a discretization of $\Omega$ with point set $\mathcal{X} = {x_1, \dots, x_N} \subseteq \Omega$ can be assessed with standard concepts such as&amp;lt;ref name=&amp;quot;ScatteredData&amp;quot;&amp;gt;H. Wendland, Scattered data approximation, vol. 17, Cambridge university press, 2004.&amp;lt;/ref&amp;gt;:&lt;br /&gt;
\begin{align*}&lt;br /&gt;
r_{\max, \mathcal{X}} = \sup_{x \in \Omega} \min_{1 \leq j \leq N} \|x - x_j\| &amp;amp; \quad \dots \quad \text{maximum empty sphere radius}, \\&lt;br /&gt;
r_{\min, \mathcal{X}} = \frac{1}{2} \min_{i \neq j} \| x_i - x_j \| &amp;amp; \quad \dots \quad \text{separation distance}. \\&lt;br /&gt;
\end{align*}&lt;br /&gt;
&lt;br /&gt;
== Filling domain interior with nodes ==&lt;br /&gt;
TODO(Uduh): rewrite&amp;lt;ref name=&amp;quot;GeneralFill&amp;quot;&amp;gt;J. Slak and G. Kosec, On generation of node distributions for meshless PDE discretizations,&lt;br /&gt;
SIAM Journal on Scientific Computing, 41 (2019), pp. A3202–A3229, https://doi.org/10.1137/18M1231456.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $p_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(p_i)$. A&lt;br /&gt;
set $C_i$ of new candidates is generated, which lie on the sphere with centre $p_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Remaining candidates are enqueued and node $p_i$ is marked as ``expanded''.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
Examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png]] [[File:3d_poisson_disk_sampling.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Computational times on a laptop computer, given as a rough reference. Filling a box with a hole with roughly 100 000 nodes.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: 1.57 s, of which 5% is candidate generation, 85% is spatial queries and 4% is spatial inserts&lt;br /&gt;
* 2D, KDGrid: 0.35 s, of which 19% is candidate generation, 56% is spatial queries and 0.002% is spatial inserts&lt;br /&gt;
* 3D, KDTree: 7.87 s, of which 6% is candidate generation, 89% is spatial queries and 1% is spatial inserts&lt;br /&gt;
* 3D, KDGrid: 2.58 s, of which 16% is candidate generation, 70% is spatial queries and 0.001% is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with N, with larger N increasing spatial query share by 2 percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
TODO(Uduh): rewrite&amp;lt;ref name=&amp;quot;GeneralSurfaceFill&amp;quot;&amp;gt;U. Duh, G. Kosec and J. Slak, Fast variable density node generation on parametric surfaces with application to mesh-free methods, arXiv preprint arXiv:2005.08767 (2020).&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere.&lt;br /&gt;
&lt;br /&gt;
Here are some examples of curves and surfaces filled with the described algorithm.&lt;br /&gt;
&lt;br /&gt;
[[File:2d_simp.png|400px]] [[File:3d_complex.png|400px]] [[File:3d_simple.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The described algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries.&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
TODO(Uduh): rewrite&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3050</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3050"/>
				<updated>2020-09-09T11:01:48Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Filling domain with nodes ==&lt;br /&gt;
TODO(Uduh): rewrite&lt;br /&gt;
&lt;br /&gt;
The goal is to an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(p)$. &lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $p_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(p_i)$. A&lt;br /&gt;
set $C_i$ of new candidates is generated, which lie on the sphere with centre $p_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Remaining candidates are enqueued and node $p_i$ is marked as ``expanded''.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
Examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png]] [[File:3d_poisson_disk_sampling.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Computational times on a laptop computer, given as a rough reference. Filling a box with a hole with roughly 100 000 nodes.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: 1.57 s, of which 5% is candidate generation, 85% is spatial queries and 4% is spatial inserts&lt;br /&gt;
* 2D, KDGrid: 0.35 s, of which 19% is candidate generation, 56% is spatial queries and 0.002% is spatial inserts&lt;br /&gt;
* 3D, KDTree: 7.87 s, of which 6% is candidate generation, 89% is spatial queries and 1% is spatial inserts&lt;br /&gt;
* 3D, KDGrid: 2.58 s, of which 16% is candidate generation, 70% is spatial queries and 0.001% is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with N, with larger N increasing spatial query share by 2 percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
TODO(Uduh): rewrite&lt;br /&gt;
&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere.&lt;br /&gt;
&lt;br /&gt;
Here are some examples of curves and surfaces filled with the described algorithm.&lt;br /&gt;
&lt;br /&gt;
[[File:2d_simp.png|400px]] [[File:3d_complex.png|400px]] [[File:3d_simple.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The described algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries.&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
TODO(Uduh): rewrite&lt;br /&gt;
&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3049</id>
		<title>Medusa</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Medusa&amp;diff=3049"/>
				<updated>2020-09-03T09:04:20Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--__NOTITLE__--&amp;gt;&lt;br /&gt;
'''Welcome to the Medusa wiki. To visit the main website, go to [http://e6.ijs.si/medusa/ http://e6.ijs.si/medusa/].'''&lt;br /&gt;
&lt;br /&gt;
In [http://e6.ijs.si/ParallelAndDistributedSystems/ Parallel and Distributed Systems Laboratory] we are working on a C++ library that is first and foremost focused on tools for solving Partial Differential Equations by meshless methods. The basic idea is to create generic codes for tools that are needed for solving not only PDEs but many other problems, e.g. Moving Least Squares approximation, $k$-d tree, domain generation engines, etc.&lt;br /&gt;
We call this open source meshless project [http://e6.ijs.si/medusa/ Medusa: Coordinate Free Meshless Method implementation (MM)].&lt;br /&gt;
&lt;br /&gt;
Technical details about code and examples  can be found on our [http://e6.ijs.si/medusa/docs/ documentation page] and [https://gitlab.com/e62Lab/medusa Gitlab repository]. [[File:C.png|100px||link=https://gitlab.com/e62Lab/medusa|alt=Alt text|code]] [[File:doxygen.png|100px|link=http://e6.ijs.si/medusa/docs/|alt=Alt text|Documentation page]]&lt;br /&gt;
&lt;br /&gt;
This wiki site is meant for more relaxed discussions about general principles, possible and already implemented applications, preliminary analyses, etc.&lt;br /&gt;
Note, that there are many grammatical mistakes, typos, stupid sentences, etc. This wiki is meant for quick information exchange and therefore we do not invest a lot of energy into styling :).  &lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
* [https://gitlab.com/e62Lab/medusa Code on Gitlab]&lt;br /&gt;
* [[How to build | Installation and building]]&lt;br /&gt;
* [[Including this library in your project | Including this library in your project]]&lt;br /&gt;
* [[Testing | Running tests]]&lt;br /&gt;
* [http://e6.ijs.si/medusa/docs/ Technical documentation]&lt;br /&gt;
* [[Coding style | Coding style]]&lt;br /&gt;
* [[Wiki editing guide | Wiki editing and backup guide]]&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
In this section we present exact examples. Each of the below solutions can be found also in in the repository under examples. More explanation about the physical background and solution procedure can be found in following sections.&lt;br /&gt;
* [[Philosophy of examples and how to run them]]&lt;br /&gt;
* [[Poisson's equation]]&lt;br /&gt;
* [[Heat equation]]&lt;br /&gt;
* [[Linear elasticity]]&lt;br /&gt;
* [[Complex-valued problems]]&lt;br /&gt;
* [[Coupled domains]]&lt;br /&gt;
* [[Parametric domains | Parametric domains &amp;amp;ndash; Curved surface with variable density]]&lt;br /&gt;
* [[NURBS domains | Domains modeled with non-uniform rational basis spline's (NURBS)]]&lt;br /&gt;
* [[Customization]]&lt;br /&gt;
* [[Ghost nodes]]&lt;br /&gt;
* [[Electromagnetic scattering]]&lt;br /&gt;
* [[Schrödinger equation]]&lt;br /&gt;
* [[Wave equation]]&lt;br /&gt;
* [[Cahn-Hilliard equation]]&lt;br /&gt;
* [[Meshless Lattice Boltzmann method]]&lt;br /&gt;
&lt;br /&gt;
== Building blocks ==&lt;br /&gt;
Medusa is modular coordinate-free parallel implementation of a numerical framework designed, but not limited to, for solving PDEs. In this section we present main modules of the library that can be also used as a standalone tools. &lt;br /&gt;
* [[Positioning of computational nodes]] &lt;br /&gt;
* [[k-d tree|''k''-d tree]] and other spatial search structures&lt;br /&gt;
* Solving [[Solving linear systems | linear systems]], [[Solving overdetermined systems | overdetermined]] and [[Solving underdetermined systems | underdetermined]]&lt;br /&gt;
* [[Weighted Least Squares (WLS)]]&lt;br /&gt;
* [[Computation of shape functions]]&lt;br /&gt;
* [[Meshless Local Strong Form Method (MLSM)]]&lt;br /&gt;
* [[Radial basis function-generated finite differences (RBF-FD)]]&lt;br /&gt;
* [[Ghost nodes (theory)]]&lt;br /&gt;
* [[Integrators for time stepping]]&lt;br /&gt;
* [[RBF Interpolation]]&lt;br /&gt;
&lt;br /&gt;
== Discussions / Applications ==&lt;br /&gt;
This section is meant for general discussion about the physical background of the examples, the solution procedures, various applications, etc. Note, that code snippets presented in discussion might not reflect the actual state of Medusa.  &lt;br /&gt;
* Basic PDE solutions&lt;br /&gt;
** [[Convection Diffusion equation | Convection Diffusion equation]]&lt;br /&gt;
**[[Wave equation application]] &lt;br /&gt;
* [[Adaptivity]]&lt;br /&gt;
* [[Solid Mechanics]]&lt;br /&gt;
** [[Point contact]]&lt;br /&gt;
** [[Hertzian contact]]&lt;br /&gt;
** [[Cantilever beam]]&lt;br /&gt;
** [[Fretting fatigue case]]&lt;br /&gt;
* [[Fluid Mechanics]]&lt;br /&gt;
** [[Lid driven cavity]]&lt;br /&gt;
** [[de Vahl Davis natural convection test]]&lt;br /&gt;
** [[Natural convection in 3D irregular domain]]&lt;br /&gt;
** [[Natural convection from heated cylinder]]&lt;br /&gt;
** [[Natural convection between concentric cylinders]]&lt;br /&gt;
* [[Computational electromagnetics]]&lt;br /&gt;
** [[Triple dielectric step in 1D]]&lt;br /&gt;
** [[Scattering from an infinite cylinder]]&lt;br /&gt;
** [[Point source near an anisotropic lens]]&lt;br /&gt;
* Other applications&lt;br /&gt;
** [[Attenuation due to liquid water content in the atmosphere|Attenuation of a satellite communication]]&lt;br /&gt;
** [[Heart rate variability detection]]&lt;br /&gt;
** [[Bioheat equation]]&lt;br /&gt;
&lt;br /&gt;
== Performance analyses ==&lt;br /&gt;
* [[Execution on Intel® Xeon Phi™ co-processor]]&lt;br /&gt;
* [[1D MLSM and FDM comparison]]&lt;br /&gt;
* [[:File:tech_report.pdf|Execution overheads due to clumsy types::technical report]] [[File:pdf-file.gif]]&lt;br /&gt;
* [[Solving sparse systems]]&lt;br /&gt;
* [[Eigen paralelization]]&lt;br /&gt;
&lt;br /&gt;
== Last changes ==&lt;br /&gt;
&amp;lt;news unique=1 limit = 5&amp;gt;&lt;br /&gt;
*{{{timeanddate}}} :: {{{title}}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/news&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous ==&lt;br /&gt;
* FAQ  - [[Frequently asked questions]]. &lt;br /&gt;
* [[List of wiki contributors]]&lt;br /&gt;
* List of library contributors: [http://e6.ijs.si/medusa/about#about-contributors See the official website]&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
* Slak J., Kosec G. Adaptive radial basis function-generated finite differences method for contact problems. International journal for numerical methods in engineering, ISSN 0029-5981 [http://www-e6.ijs.si/ParallelAndDistributedSystems/pdf/32230439.pdf manuscript]&lt;br /&gt;
* Slak J., Kosec G.; Refined meshless local strong form solution of Cauchy-Navier equation on an irregular domain. Engineering analysis with boundary elements. 2018;11 ; [http://comms.ijs.si/~gkosec/data/papers/31107623.pdf manuscript]&lt;br /&gt;
* Depolli, M., Kosec, G., Assessment of differential evolution for multi-objective optimization in a natural convection problem solved by a local meshless method. Engineering optimization, 2017, vol. 49, no. 4, pp. 675-692 ;[http://comms.ijs.si/~gkosec/data/papers/29639719.pdf manuscript]&lt;br /&gt;
* Kosec G., A local numerical solution of a fluid-flow problem on an irregular domain. Advances in engineering software. 2016;7 ; [29512743] ; [http://comms.ijs.si/~gkosec/data/papers/29512743.pdf manuscript]&lt;br /&gt;
* Kosec G., Trobec R., Simulation of semiconductor devices with a local numerical approach. Engineering analysis with boundary elements. 2015;69-75; [27912487] ; [http://comms.ijs.si/~gkosec/data/papers/27912487.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., Simulation of macrosegregation with mesosegregates in binary metallic casts by a meshless method. Engineering analysis with boundary elements. 2014;36-44; [http://comms.ijs.si/~gkosec/data/papers/3218939.pdf manuscript]&lt;br /&gt;
* Kosec G., Depolli M., Rashkovska A., Trobec R., Super linear speedup in a local parallel meshless solution of thermo-fluid problem. Computers &amp;amp; Structures. 2014;133:30-38; [http://comms.ijs.si/~gkosec/data/papers/27339815.pdf manuscript]&lt;br /&gt;
* Kosec G., Zinterhof P., Local strong form meshless method on multiple Graphics Processing Units. Computer modeling in engineering &amp;amp; sciences. 2013;91:377-396; [http://comms.ijs.si/~gkosec/data/papers/26785063.pdf manuscript]&lt;br /&gt;
* Kosec G., Šarler B., H-adaptive local radial basis function collocation meshless method. Computers, materials &amp;amp; continua. 2011;26:227-253; [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerBurgers.pdf manuscript]&lt;br /&gt;
* Trobec R., Kosec G., Šterk M., Šarler B., Comparison of local weak and strong form meshless methods for 2-D diffusion equation. Engineering analysis with boundary elements. 2012;36:310-321; [http://comms.ijs.si/~gkosec/data/papers/EABE2499.pdf manuscript]&lt;br /&gt;
* Kosec G, Zaloznik M, Sarler B, Combeau H. A Meshless Approach Towards Solution of Macrosegregation Phenomena. CMC: Computers, Materials, &amp;amp; Continua. 2011;580:1-27 [http://comms.ijs.si/~gkosec/data/papers/KosecZaloznikSarlerCombeauSegregation.pdf manuscript]&lt;br /&gt;
* Kosec G, Sarler B. Solution of thermo-fluid problems by collocation with local pressure correction. International Journal of Numerical Methods for Heat &amp;amp; Fluid Flow. 2008;18:868-82 [http://comms.ijs.si/~gkosec/data/papers/KosecSarlerNS2008.pdf manuscript]&lt;br /&gt;
*  Trobec R., Kosec G., Parallel Scientific Computing, ISBN: 978-3-319-17072-5 (Print) 978-3-319-17073-2.&lt;br /&gt;
*  Slak, J., Kosec, G.. Detection of heart rate variability from a wearable differential ECG device., MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938, pp 450-455.&lt;br /&gt;
*  Kolman, M., Kosec, G. Correlation between attenuation of 20 GHz satellite communication link and liquid water content in the atmosphere. MIPRO 2016, 39th International Convention, 2016, Opatija, Croatia, ISSN 1847-3938. pp. 308-313.&lt;br /&gt;
&lt;br /&gt;
==Related pages==&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/#!NumericalMethods&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/#!utils&lt;br /&gt;
* http://e6.ijs.si/ParallelAndDistributedSystems/#!NUMA&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3048</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3048"/>
				<updated>2020-09-03T08:58:58Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Filling domain with nodes ==&lt;br /&gt;
The goal is to an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(p)$. &lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $p_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(p_i)$. A&lt;br /&gt;
set $C_i$ of new candidates is generated, which lie on the sphere with centre $p_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Remaining candidates are enqueued and node $p_i$ is marked as ``expanded''.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
Examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png]] [[File:3d_poisson_disk_sampling.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Computational times on a laptop computer, given as a rough reference. Filling a box with a hole with roughly 100 000 nodes.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: 1.57 s, of which 5% is candidate generation, 85% is spatial queries and 4% is spatial inserts&lt;br /&gt;
* 2D, KDGrid: 0.35 s, of which 19% is candidate generation, 56% is spatial queries and 0.002% is spatial inserts&lt;br /&gt;
* 3D, KDTree: 7.87 s, of which 6% is candidate generation, 89% is spatial queries and 1% is spatial inserts&lt;br /&gt;
* 3D, KDGrid: 2.58 s, of which 16% is candidate generation, 70% is spatial queries and 0.001% is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with N, with larger N increasing spatial query share by 2 percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere.&lt;br /&gt;
&lt;br /&gt;
Here are some examples of curves and surfaces filled with the described algorithm.&lt;br /&gt;
&lt;br /&gt;
[[File:2d_simp.png|400px]] [[File:3d_complex.png|400px]] [[File:3d_simple.png|400px]]&lt;br /&gt;
&lt;br /&gt;
The described algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries.&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:2d_simp.png&amp;diff=3045</id>
		<title>File:2d simp.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:2d_simp.png&amp;diff=3045"/>
				<updated>2020-09-03T08:57:29Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:3d_complex.png&amp;diff=3046</id>
		<title>File:3d complex.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:3d_complex.png&amp;diff=3046"/>
				<updated>2020-09-03T08:57:29Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=File:3d_simple.png&amp;diff=3047</id>
		<title>File:3d simple.png</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=File:3d_simple.png&amp;diff=3047"/>
				<updated>2020-09-03T08:57:29Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: File uploaded with MsUpload&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File uploaded with MsUpload&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3044</id>
		<title>Positioning of computational nodes</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=Positioning_of_computational_nodes&amp;diff=3044"/>
				<updated>2020-09-03T08:37:16Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since one of the most attractive features of mesh-free methods is the ability to use nodes&lt;br /&gt;
without any connectivity information, node placing was considered much easier than mesh generation&lt;br /&gt;
or simply used existing tools for mesh generation and was thus often disregarded,&lt;br /&gt;
sometimes implying that any nodes could be used, even if placed at random.&lt;br /&gt;
It soon turned out that that is not the case, mostly with strong form methods,&lt;br /&gt;
since many methods require regular nodes for good performance and bad distributions&lt;br /&gt;
can impact their stability.&lt;br /&gt;
&lt;br /&gt;
One of the key successes of RBF based mesh free methods, such as RBF-generated finite differences&lt;br /&gt;
(RBF-FD) is the ability to use highly spatially variable node distributions which can&lt;br /&gt;
adapt to irregular geometries and allow for refinement in critical areas.&lt;br /&gt;
We present our algorithm below.&lt;br /&gt;
&lt;br /&gt;
The last set of algorithms deals with the refinement of the nodal distribution which iteratively improves &lt;br /&gt;
generated node sets.&lt;br /&gt;
&lt;br /&gt;
== Filling domain with nodes ==&lt;br /&gt;
The goal is to an arbitrary domain $\Omega \subseteq \R^d$ with nodes following the given target spacing function $h(p)$. &lt;br /&gt;
&lt;br /&gt;
We start with a simple algorithm based on '''Poisson Disk Sampling''' (PDS) that results in a relatively tightly packed distribution of nodes.&lt;br /&gt;
The algorithm beings with a given non-empty set of nodes called &amp;quot;seed nodes&amp;quot;.&lt;br /&gt;
A single seed node placed anywhere in the domain interior is needed to begin the&lt;br /&gt;
algorithm and if none are provided, one can be chosen at random.&lt;br /&gt;
However, in the context of PDE discretisations, some nodes on the boundary are usually&lt;br /&gt;
already known and can be used as seed nodes, possibly along with additional nodes in the interior.&lt;br /&gt;
&lt;br /&gt;
The initial nodes are put in a queue. In each iteration $i$, a new node $p_i$ is dequeued.&lt;br /&gt;
Its desired nodal spacing $r_i$ is obtained from the function $h$, $r_i = h(p_i)$. A&lt;br /&gt;
set $C_i$ of new candidates is generated, which lie on the sphere with centre $p_i$ and radius $r_i$.&lt;br /&gt;
New candidates are spaced uniformly with a random rotation.&lt;br /&gt;
Candidates that lie outside of the domain or are too close to already existing nodes&lt;br /&gt;
are rejected. Remaining candidates are enqueued and node $p_i$ is marked as ``expanded''.&lt;br /&gt;
The iteration continues until the queue is empty.&lt;br /&gt;
&lt;br /&gt;
Examples of discretized 2D and 3D domains.&lt;br /&gt;
&lt;br /&gt;
[[File:2d_poisson_disk_sampling.png]] [[File:3d_poisson_disk_sampling.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Computational times on a laptop computer, given as a rough reference. Filling a box with a hole with roughly 100 000 nodes.&lt;br /&gt;
&lt;br /&gt;
* 2D, KDTree: 1.57 s, of which 5% is candidate generation, 85% is spatial queries and 4% is spatial inserts&lt;br /&gt;
* 2D, KDGrid: 0.35 s, of which 19% is candidate generation, 56% is spatial queries and 0.002% is spatial inserts&lt;br /&gt;
* 3D, KDTree: 7.87 s, of which 6% is candidate generation, 89% is spatial queries and 1% is spatial inserts&lt;br /&gt;
* 3D, KDGrid: 2.58 s, of which 16% is candidate generation, 70% is spatial queries and 0.001% is spatial inserts &lt;br /&gt;
&lt;br /&gt;
Percentages vary slightly with N, with larger N increasing spatial query share by 2 percent points.&lt;br /&gt;
&lt;br /&gt;
== Filling parametric surfaces ==&lt;br /&gt;
The algorithm from the previous section can be modified to work on domain boundaries, for example curves in 2D and surfaces in 3D. Let $\partial \Omega$ be a domain boundary parametrized with a regular parametrization $\boldsymbol{r}: \Lambda \subset \mathbb{R}^{d - 1} \to \partial \Omega \subset \mathbb{R}^{d}$ and let $h(\boldsymbol{p})$ be our spacing function.&lt;br /&gt;
&lt;br /&gt;
We can consider our problem as filling the domain $\Lambda$ in a way, that when its nodes are mapped by $\boldsymbol{r}$, they are approximately $h$ apart. The general logic of iteratively expanding nodes can thus stay the same, we only need to generate different candidates. Let $\boldsymbol{\lambda}_i \in \Lambda$ be the parameter we wish to expand. We want to generate candidates $\boldsymbol{\eta}_{i,j} \in H_i \subset \Lambda$ so that&lt;br /&gt;
\begin{equation}&lt;br /&gt;
||\boldsymbol{r}(\boldsymbol{\eta}_{i,j}) - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = h(\boldsymbol{r}(\boldsymbol{\lambda}_i)).&lt;br /&gt;
\end{equation}&lt;br /&gt;
Let&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\boldsymbol{\eta}_{i,j} = \boldsymbol{\lambda}_i + \alpha_{i, j} \vec{s}_{i,j},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $\vec{s}_{i,j}$ is a unit vector and $\alpha_{i, j} &amp;gt; 0$. By using the first order Taylor's expansion we get&lt;br /&gt;
\begin{align}&lt;br /&gt;
h(\boldsymbol{r}(\boldsymbol{\lambda}_i)) &amp;amp;\approx ||\boldsymbol{r}(\boldsymbol{\lambda}_i) + \alpha_{i, j} \nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j} - \boldsymbol{r}(\boldsymbol{\lambda}_i)|| = \alpha_{i, j} ||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||, \\&lt;br /&gt;
\alpha_{i, j} &amp;amp;\approx \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||}.&lt;br /&gt;
\end{align}&lt;br /&gt;
Therefore, our set of candidates for expansion of $\boldsymbol{\lambda}_i$ can be expressed as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
H_i = \left\{ \boldsymbol{\lambda}_i + \frac{h(\boldsymbol{r}(\boldsymbol{\lambda}_i))}{||\nabla \boldsymbol{r}(\boldsymbol{\lambda}_i) \vec s_{i, j}||} \vec{s}_{i, j} ; \vec{s}_{i,j} \in S_i, \right\}&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $S_i$ is a random discretization of a unit sphere.&lt;br /&gt;
&lt;br /&gt;
Here are some examples of curves and surfaces filled with the described algorithm.&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
The described algorithm can also be used to fill surfaces defined by multiple patches, such as non-uniform rational basis spline (NURBS) models generated by Computer aided design (CAD) software. It is usually beneficial to discretize patch boundaries ($\partial \partial \Omega$) first, since it ensures no gaps of size between $h(\boldsymbol{p})$ and $2h(\boldsymbol{p})$ on patch boundaries.&lt;br /&gt;
&lt;br /&gt;
== Relaxation of the nodal distribution ==&lt;br /&gt;
To construct stable and reliable shape functions the support domains need to be non-degenerated [1], i.e. the distances between support nodes have to be balanced. Naturally, this condition is fulfilled in regular nodal distributions, but when working with complex geometries, the nodes have to be positioned accordingly. There are different algorithms designed to optimally fill the domain with different shapes [2, 3]. Here an intrinsic feature of the MLSM is used to take care of that problem. The goal is to minimize the overall support domain degeneration in order to attain stable numerical solution. In other words, a global optimization problem with the overall deformation of the local support domains acting as the cost function is tackled. We seek the global minimum by a local iterative approach. In each iteration, the computational nodes are translated according to the local derivative of the potential &lt;br /&gt;
\begin{equation}&lt;br /&gt;
	\delta \b{p}\left( \b{p} \right)=-\sigma_{k}\sum\limits_{n=1}^{n}{\nabla }V\left( \mathbf{p}-\b{p}_n \right)&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $V, n, \delta \b{p}, \b{p}_{n}$ and $\sigma_{k}$ stand for the potential, number of support nodes, offset of the node, position of n-th support node and relaxation parameter, respectively. After offsets in all nodes are computed, the nodes are repositioned as&lt;br /&gt;
$\b{p}\leftarrow \b{p}+\delta \b{p}\left( \b{p} \right)$. &lt;br /&gt;
Presented iterative process procedure begins with positioning of boundary nodes, which is considered as the definition of the domain, and then followed by the positioning of internal nodes. &lt;br /&gt;
&lt;br /&gt;
The BasicRelax Engine  supports two call types:&lt;br /&gt;
* with supplied distribution function relax(func), where it tries to satisfy the user supplied nodal density function. This can be achieved only when there is the total number of domain nodes the same as integral of density function over the domain. If there is too much nodes a volatile relax might occur. If there is not enough nodes the relax might become lazy. The best use of this mode is in combination with fillDistribution Engines.&lt;br /&gt;
* without distribution, where nodes always move towards less populated area. The relax magnitude is simply determined from Annealing factor and distance to the closest node. A simple and stable approach, however, note that this relax always converges towards uniformly distributed nodes.&lt;br /&gt;
&lt;br /&gt;
Example of filling and relaxing 2D domain can be found in below code snippet and Figure. Note the difference between relax without supplied distribution (right) and with supplied distribution (left). The quiver plot represents normal vectors in boundary nodes. &lt;br /&gt;
More examples can be found in main repository under tests.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
    double r = 0.25;&lt;br /&gt;
    CircleDomain&amp;lt;Vec2d&amp;gt; c({0.5, 0.5}, r);&lt;br /&gt;
&lt;br /&gt;
    BasicRelax relax;&lt;br /&gt;
    relax.iterations(100).InitialHeat(1).FinalHeat(0).projectionType(1).numNeighbours(3);&lt;br /&gt;
    relax.boundaryProjectionThreshold(0.55);&lt;br /&gt;
    auto fill_density = [](Vec2d p) -&amp;gt; double {&lt;br /&gt;
        return (0.005 + (p[0] - 0.5) * (p[0] - 0.5) / 2 + (p[1] - 0.5) * (p[1] - 0.5) / 2);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    c.fillUniformBoundaryWithStep(fill_density(Vec2d({r, 0.0})));&lt;br /&gt;
    PoissonDiskSamplingFill fill_engine;&lt;br /&gt;
&lt;br /&gt;
    fill_engine(c, fill_density);&lt;br /&gt;
    relax(c);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:relax_with_dist.png|600px]] [[File:relax_no_dist.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[1] Lee CK, Liu X, Fan SC. Local muliquadric approximation for solving boundary value problems. Comput Mech. 2003;30:395-409. &lt;br /&gt;
&lt;br /&gt;
[2] Löhner R, Oñate E. A general advancing front technique for filling space with arbitrary objects. Int J Numer Meth Eng. 2004;61:1977-91.&lt;br /&gt;
&lt;br /&gt;
[3] Liu Y, Nie Y, Zhang W, Wang L. Node placement method by bubble simulation and its application. CMES-Comp Model Eng. 2010;55:89.&lt;br /&gt;
&lt;br /&gt;
== Refinement of the nodal distribution ==&lt;br /&gt;
&lt;br /&gt;
Here we consider possible meshless refinement algorithms (sometimes also called adaptive cloud refinement). The refinement mechanisms we have so far studied include:&lt;br /&gt;
* refinement based on closest node distance&lt;br /&gt;
* refinement based on averaged (inter-)node distance&lt;br /&gt;
* refinement based on half-links&lt;br /&gt;
&lt;br /&gt;
Here we only want to compare the quality of the refined grids and have not tied the refinement algorithm with a error indicator, thus we only study the node insertion process by refining the whole grid. &lt;br /&gt;
&lt;br /&gt;
The refinement routine takes a range of nodes (e.g. a subregion of the domain) together with the refinement parameters and generates new nodes around the old ones. Special care must be taken with refinement of the boundary nodes. Points have to be selected on the actual boundary either analytically considering the geometry or with a numerical root finder such as bisection. &lt;br /&gt;
&lt;br /&gt;
====Problem description====&lt;br /&gt;
&lt;br /&gt;
To compare the node refinement mechanisms we study the process of reaction-diffusion in an infinite cylindrical catalyst pellet (infinite in the $z$-dimension). Since the pellet is infinite in one dimension this problem simplifies to a 2D problem (in the $xy$-plane). For a catalyst pellet of radius $R$ centered at $(x,y) = (0,0)$ and the reactant undergoing a first order reaction we must solve the equation&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\b{\nabla}^2 C - {M_T}^2 C = 0,&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $C$ is the concentration of the reactant, $M_T = R\sqrt{k/D}$ is known as Thiele's modulus and $k$ and $D$ represent the reaction rate constant and diffusivity of the reacting species. The boundary conditions for this problem is \[C(R) = C_s.\] The analytical solution can be found easily using cylindrical coordinates and is given by&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\frac{C(r)}{C_S} = \frac{I_0(r M_T)}{I_0(R M_T)}, &lt;br /&gt;
\end{equation}&lt;br /&gt;
where $I_0(r)$ is the modified Bessel function of first kind (this function is available in the library Boost as well as scripting languages such as Python or MATLAB). The conversion from cartesian to cylindrical coordinates is given by \[r = \sqrt{x^2+y^2}.\]&lt;br /&gt;
&lt;br /&gt;
==== Error indicators ====&lt;br /&gt;
&lt;br /&gt;
To compare the quality of the refined meshes for the described problem case we look at different error criteria including the max norm $L_\infty$ defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
L_\infty = \mathrm{max}_i \left|C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right|,&lt;br /&gt;
\end{equation}&lt;br /&gt;
the $L_2$ norm per node defined as&lt;br /&gt;
\begin{equation}&lt;br /&gt;
\bar{L_2} = \frac{\sqrt{\sum^N_{i = 1}\left(C_i^\mathrm{numerical} - C_i^\mathrm{analytical}\right)^2}}{N},&lt;br /&gt;
\end{equation}&lt;br /&gt;
where $N$ is the number of nodes (and pertinent equations) in the domain.&lt;br /&gt;
&lt;br /&gt;
We also measure the number of iterations required by the sparse BiCGSTAB solver to reach convergence and the estimated error of solving the system of equations.&lt;br /&gt;
&lt;br /&gt;
== Closest node ==&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0 = (x_0,y_0)$:&lt;br /&gt;
&lt;br /&gt;
# find the closest node $\b{x}_1 = (x_1,y_1)$   &lt;br /&gt;
# calculate the half distance between the two nodes \[d = |\b{x}_1 - \b{x}_0|/2\]&lt;br /&gt;
# randomly select up to 6 (The case of 6 nodes is the limit since it produces a regular hexagon. In practice this never occurs due to the &amp;quot;monte carlo&amp;quot; node selection procedure.) new nodes on the circle with center $\b{x}_0$ and radius $d$ and simultaneously make sure their is a minimal inter-nodal distance $d$ between the new nodes. &lt;br /&gt;
&lt;br /&gt;
For boundary points we first select 2 points that intersect with the boundary of the domain and only then points lying inside the domain. Due to geometrical constraints boundary points will usually end up with 3 new nodes (in case of straight boundaries we could end up with 4, which would be the previously discussed hexagon limit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_1&amp;quot;&amp;gt;&lt;br /&gt;
[[File:closest_node.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on closest node approach (initial unrefined grid is on the left). In the second refinement step an erroneous point has appeared from an internal point that was too close to the boundary. Also noticable is clustering of points on the boundary.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Average radius ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $f$ and $l_s$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes&lt;br /&gt;
# calculate the average distance $\bar{d}$ to the $l_s$ closest nodes&lt;br /&gt;
# randomly select up to 6 new nodes on the circle with center $\b{x}_0$ and radius $f\cdot\bar{d}$ where $f$ is the radius fraction that lies between 0.2 (leads to clustering) and 0.8. Only allow nodes that are separated by the distance $f \cdot \bar{d}$. &lt;br /&gt;
&lt;br /&gt;
''(note that in case $l_s = 1$ and $f = 0.5$ the average radius mechanism becomes equal to the closest node refinement approach described above)''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_2&amp;quot;&amp;gt;&lt;br /&gt;
[[File:new_average_radius.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on average radius approach (initial unrefined grid is on the left). The parameters are $l_s = 5$ closest nodes in average radius calculation and points placed at radius fraction $f = 0.5$. &amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half-links ==&lt;br /&gt;
&lt;br /&gt;
Input parameters: $l_s$, $d_m$&lt;br /&gt;
&lt;br /&gt;
For a given node $\b{x}_0$:&lt;br /&gt;
# find the $l_s$ (an integer from 1 to 7) closest nodes $\b{x}_i$&lt;br /&gt;
# select new nodes in the middle of the segments $\b{x}_i - \b{x}_0$ only allowing points that are separated by the minimal distance $d_m$&lt;br /&gt;
&lt;br /&gt;
''(note also that in the 1D case the half-link and closest radius approach become the same)''&lt;br /&gt;
&lt;br /&gt;
The minimal distance $d_m$ is chosen as a fraction of the distance to the closest link, e.g. $d_m = f d$, where $f$ is the provided fraction and $d$ is the distance to the closest link.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3&amp;quot;&amp;gt;&lt;br /&gt;
[[File:half_link.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links (initial unrefined grid is on the left). The parameters are $l_s = 6$ and $d_m = 0.4 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_3a&amp;quot;&amp;gt;&lt;br /&gt;
[[File:refineWithRelax.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links with additional 10 step relax after refinement&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After experimentation we noticed there are some inconsistencies when trying to refine structured point sets with this approach. The reason for these inconsistencies is that the boundary and internal points have a different number of &amp;quot;natural neighbours&amp;quot;. For example in 2D on a square grid, the internal points have 8 neighbours, while boundary points have 5 neighbours. If we choose higher numbers e.g 9 links for an internal node, the 9th node might be any of the 4 nodes one shell further out that only differ at machine precision.&lt;br /&gt;
&lt;br /&gt;
The figures below show some preliminary results of refinement based on half-links. For the circle domain relaxation was applied after the refinement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:square_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:dc_field.png|1000px|thumb|center|&amp;lt;caption&amp;gt; Thermal diffusion in (convective) flow at a stagnation point (bottom left corner).&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the second refinement of the corner, the solver had difficulty converging to the solution. This was the result of a fixed size shape parameter in the shape functions of the node points. The shape functions have to be tailored to the local characteristic distance in the point set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:circle_refinement&amp;quot;&amp;gt;&lt;br /&gt;
[[File:ref_circle.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Reaction-diffusion in a cylinder catalyst. Two successive refinements have been applied for $r &amp;gt; 0.5$ and $r &amp;gt; 0.8$, where $r$ is the radial coordinate. The cylinder radius $R = 1$.$&amp;lt;/caption&amp;gt;]] &lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hybrid approach ==&lt;br /&gt;
&lt;br /&gt;
A hybrid might give better distributions of the refined points. The half-link approach performs well at the boundaries while the distance approach gives less regular internal distributions. In any case it is suggested to perform a few more relaxation steps to equilibrate the mesh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;figure id=&amp;quot;fig:node_refinement_4&amp;quot;&amp;gt;&lt;br /&gt;
[[File:hybrid_refine.png|1000px|thumb|center|&amp;lt;caption&amp;gt;Refinement based on half links at the boundaries and closest distances for the internal nodes (initial unrefined grid is on the left). for the boundary nodes the parameters are $l_s = 7$ and $d_m = 0.5 d$, where $d$ is the distance to the closest link.&amp;lt;/caption&amp;gt;]]&lt;br /&gt;
&amp;lt;/figure&amp;gt;&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	<entry>
		<id>https://e6.ijs.si/medusa/wiki/index.php?title=NURBS_domains&amp;diff=3043</id>
		<title>NURBS domains</title>
		<link rel="alternate" type="text/html" href="https://e6.ijs.si/medusa/wiki/index.php?title=NURBS_domains&amp;diff=3043"/>
				<updated>2020-09-01T11:32:02Z</updated>
		
		<summary type="html">&lt;p&gt;Uduh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Go back to [[Medusa#Examples|Examples]].&lt;br /&gt;
&lt;br /&gt;
Medusa supports filling domains bounded by non-uniform rational basis splines ([https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline, NURBS]) curves and NURBS surfaces obtained as the tensor product of two NURBS curves. Note that [https://en.wikipedia.org/wiki/B%C3%A9zier_curve Bézier curves] and [https://en.wikipedia.org/wiki/B-spline B-splines] are special cases of NURBS curves.&lt;br /&gt;
&lt;br /&gt;
See [[Positioning of computational nodes]] for details on node positioning algorithms.&lt;br /&gt;
&lt;br /&gt;
== Poisson equation with Dirichlet boundary conditions in 2D ==&lt;br /&gt;
With Medusa, we can also solve partial differential equations on NURBS domains. Consider the solution of a simple 2D Poisson equation with Dirichlet boundary conditions:&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    	\Delta u &amp;amp;= 20      &amp;amp;&amp;amp;\text{in } \Omega, \\&lt;br /&gt;
    	  u &amp;amp;= 0           &amp;amp;&amp;amp;\text{on } \partial \Omega,&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
where $\Omega$ is the interior of a NURBS curve defined piecewise. In this case, we will use a duck shaped curve composed of $8$ NURBS curve patches. &lt;br /&gt;
&lt;br /&gt;
In Medusa, we represent NURBS patches as instances of &amp;lt;code&amp;gt;NURBSPatch&amp;lt;vec_t, param_vec_t&amp;gt;&amp;lt;/code&amp;gt; class, where &amp;lt;code&amp;gt;vec_t&amp;lt;/code&amp;gt; is the vector type of the ambient space (in this case &amp;lt;code&amp;gt;Vec2d&amp;lt;/code&amp;gt;) and &amp;lt;code&amp;gt;param_vec_t&amp;lt;/code&amp;gt; is the vector type of the parametric space (&amp;lt;code&amp;gt;Vec1d&amp;lt;/code&amp;gt; for curves and &amp;lt;code&amp;gt;Vec2d&amp;lt;/code&amp;gt; for surfaces). To construct an instance, its control points, weights, knot vector, and order $p$ must be given. In this case, we have a simple knot vector &amp;lt;code&amp;gt;{0, 0, 0, 0, 1, 1, 1, 1}&amp;lt;/code&amp;gt;, all weights equal to $1$ and $p = 3$ (this means that our curves are Bézier curves). Control points will be calculated from &amp;lt;code&amp;gt;pts&amp;lt;/code&amp;gt;. We will push all patches into one &amp;lt;code&amp;gt;Range&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Points to be used in NURBS creation.&lt;br /&gt;
Range&amp;lt;Vec2d&amp;gt; pts{{210, -132.5}, {205, -115}, {125, -35}, {85, -61}, {85, -61}, {85, -61},&lt;br /&gt;
                 {80, -65}, {75, -58}, {75, -58}, {65, 45}, {25, 25}, {-15, -16}, {-15, -16},&lt;br /&gt;
                 {-15, -16}, {-35, -28}, {-40, -32.375}, {-40, -32.375}, {-43, -35}, {-27, -40},&lt;br /&gt;
                 {-5, -40}, {-5, -40}, {50, -38}, {35, -65}, {15, -75}, {15, -75}, {-15, -95},&lt;br /&gt;
                 {-20, -140}, {45, -146}, {45, -146}, {95, -150}, {215, -150}, {210, -132.5}};&lt;br /&gt;
&lt;br /&gt;
// Calculate NURBS patches' control points, weights, knot vector and order.&lt;br /&gt;
int p = 3;&lt;br /&gt;
Range&amp;lt;double&amp;gt; weights{1, 1, 1, 1};&lt;br /&gt;
Range&amp;lt;double&amp;gt; knot_vector{0, 0, 0, 0, 1, 1, 1, 1};&lt;br /&gt;
Range&amp;lt;NURBSPatch&amp;lt;Vec2d, Vec1d&amp;gt;&amp;gt; patches;&lt;br /&gt;
&lt;br /&gt;
for (int i = 0; i &amp;lt; 8; i++) {&lt;br /&gt;
    Range&amp;lt;Vec2d&amp;gt; control_points;&lt;br /&gt;
    for (int j = 0; j &amp;lt; 4; j++) {&lt;br /&gt;
        control_points.push_back(pts[4 * i + j]);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    NURBSPatch&amp;lt;Vec2d, Vec1d&amp;gt; patch(control_points, weights, {knot_vector}, {p});&lt;br /&gt;
    patches.push_back(patch);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, we can construct a &amp;lt;code&amp;gt;NURBSShape&amp;lt;vec_t, param_vec_t&amp;gt;&amp;lt;/code&amp;gt; representing our NURBS curve from a &amp;lt;code&amp;gt;Range&amp;lt;/code&amp;gt; of patches and fill it according to the spacing $h$. Spacing can also be given in the form of a spacing function, see [[Parametric domains]].&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Create NURBS shape from a range of patches.&lt;br /&gt;
NURBSShape&amp;lt;Vec2d, Vec1d&amp;gt; shape(patches);&lt;br /&gt;
&lt;br /&gt;
// Fill the domain.&lt;br /&gt;
double h = 0.5;&lt;br /&gt;
DomainDiscretization&amp;lt;Vec2d&amp;gt; domain = shape.discretizeBoundaryWithStep(h);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After that, we can fill the interior of the domain in the usual way.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
GeneralFill&amp;lt;Vec2d&amp;gt; gf;&lt;br /&gt;
gf(domain, h);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we translate the partial differential equations of our problem into code and solve the problem, as in other examples.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c++&amp;quot; line&amp;gt;&lt;br /&gt;
// Construct the approximation engine.&lt;br /&gt;
int m = 2;  // basis order&lt;br /&gt;
Monomials&amp;lt;Vec2d&amp;gt; mon(m);&lt;br /&gt;
RBFFD&amp;lt;Polyharmonic&amp;lt;double, 3&amp;gt;, Vec2d&amp;gt; approx({}, mon);&lt;br /&gt;
&lt;br /&gt;
// Find support for the nodes.&lt;br /&gt;
int N = domain.size();&lt;br /&gt;
domain.findSupport(FindClosest(mon.size()));&lt;br /&gt;
&lt;br /&gt;
// Compute the shapes (we only need the Laplacian).&lt;br /&gt;
auto storage = domain.computeShapes&amp;lt;sh::lap&amp;gt;(approx);&lt;br /&gt;
&lt;br /&gt;
Eigen::SparseMatrix&amp;lt;double, Eigen::RowMajor&amp;gt; M(N, N);&lt;br /&gt;
Eigen::VectorXd rhs(N);&lt;br /&gt;
rhs.setZero();&lt;br /&gt;
M.reserve(storage.supportSizes());&lt;br /&gt;
&lt;br /&gt;
// Construct implicit operators over our storage.&lt;br /&gt;
auto op = storage.implicitOperators(M, rhs);&lt;br /&gt;
&lt;br /&gt;
for (int i : domain.interior()) {&lt;br /&gt;
    // set the case for nodes in the domain&lt;br /&gt;
    op.lap(i) = 20.0;&lt;br /&gt;
}&lt;br /&gt;
for (int i : domain.boundary()) {&lt;br /&gt;
    // enforce the boundary conditions&lt;br /&gt;
    op.value(i) = 0.0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Eigen::BiCGSTAB&amp;lt;decltype(M), Eigen::IncompleteLUT&amp;lt;double&amp;gt;&amp;gt; solver;&lt;br /&gt;
solver.compute(M);&lt;br /&gt;
ScalarFieldd u = solver.solve(rhs);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is the plot of $u(x, y)$.&lt;br /&gt;
&lt;br /&gt;
[[File:duck_pde.png|800px]]&lt;br /&gt;
&lt;br /&gt;
The whole example can be found as [https://gitlab.com/e62Lab/medusa/-/blob/dev/examples/poisson_equation poisson_NURBS_2D.cpp] along with the plot script that can be run by Matlab or Octave [https://gitlab.com/e62Lab/medusa/-/blob/dev/examples/poisson_equation poisson_NURBS_2D_2D.m].&lt;/div&gt;</summary>
		<author><name>Uduh</name></author>	</entry>

	</feed>