diff --git a/dev/developers/Manifest.toml b/dev/developers/Manifest.toml index 3eb4b4a..ff6448b 100644 --- a/dev/developers/Manifest.toml +++ b/dev/developers/Manifest.toml @@ -1,6 +1,6 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.10.0" +julia_version = "1.10.2" manifest_format = "2.0" project_hash = "c3f9411d0be997a1420e8a7e05dd8a940d908de1" @@ -16,9 +16,9 @@ uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" [[deps.CSTParser]] deps = ["Tokenize"] -git-tree-sha1 = "b1d309487c04e92253b55c1f803b1d6f0e136920" +git-tree-sha1 = "b544d62417a99d091c569b95109bc9d8c223e9e3" uuid = "00ebfdb7-1f24-5e51-bd34-a7502290713f" -version = "3.4.1" +version = "3.4.2" [[deps.CommonMark]] deps = ["Crayons", "JSON", "PrecompileTools", "URIs"] @@ -34,9 +34,9 @@ version = "0.3.0" [[deps.Compat]] deps = ["TOML", "UUIDs"] -git-tree-sha1 = "75bd5b6fc5089df449b5d35fa501c846c9b6549b" +git-tree-sha1 = "c955881e3c981181362ae4088b35995446298b80" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.12.0" +version = "4.14.0" weakdeps = ["Dates", "LinearAlgebra"] [deps.Compat.extensions] @@ -45,7 +45,7 @@ weakdeps = ["Dates", "LinearAlgebra"] [[deps.CompilerSupportLibraries_jll]] deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.0.5+1" +version = "1.1.0+0" [[deps.Crayons]] git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" @@ -54,9 +54,9 @@ version = "4.1.1" [[deps.DataStructures]] deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "ac67408d9ddf207de5cfa9a97e114352430f01ed" +git-tree-sha1 = "0f4b5d62a88d8f59003e43c25a8a90de9eb76317" uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.16" +version = "0.18.18" [[deps.Dates]] deps = ["Printf"] @@ -132,9 +132,9 @@ version = "0.21.4" [[deps.JuliaFormatter]] deps = ["CSTParser", "CommonMark", "DataStructures", "Glob", "Pkg", "PrecompileTools", "Tokenize"] -git-tree-sha1 = "8f5295e46f594ad2d8652f1098488a77460080cd" +git-tree-sha1 = "1c4880cb70a5c6c87ea36deccc3d7f9e7969c18c" uuid = "98e50ef6-434e-11e9-1051-2b60c6c9e899" -version = "1.0.45" +version = "1.0.56" [[deps.LibCURL]] deps = ["LibCURL_jll", "MozillaCACerts_jll"] @@ -169,7 +169,7 @@ uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [[deps.LinearElasticityBase]] deps = ["Einsum", "LinearAlgebra", "StaticArrays", "Tensorial"] -git-tree-sha1 = "c243677449a8e5e479ab88208174a114a6e98849" +git-tree-sha1 = "e9e322dd20d4fd9433ce414da7f85f7d5c4697f6" repo-rev = "main" repo-url = "https://github.com/MineralsCloud/LinearElasticityBase.jl" uuid = "c9ccf908-6911-46c3-b424-436f6a0ac525" @@ -177,9 +177,9 @@ version = "0.3.0" [[deps.LogExpFunctions]] deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "7d6dd4e9212aebaeed356de34ccf262a3cd415aa" +git-tree-sha1 = "18144f3e9cbe9b15b070288eef858f71b291ce37" uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.26" +version = "0.3.27" [deps.LogExpFunctions.extensions] LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" @@ -229,7 +229,7 @@ version = "1.2.0" [[deps.OpenBLAS_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.23+2" +version = "0.3.23+4" [[deps.OpenLibm_jll]] deps = ["Artifacts", "Libdl"] @@ -260,15 +260,15 @@ version = "1.10.0" [[deps.PrecompileTools]] deps = ["Preferences"] -git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f" +git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -version = "1.2.0" +version = "1.2.1" [[deps.Preferences]] deps = ["TOML"] -git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e" +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.4.1" +version = "1.4.3" [[deps.Printf]] deps = ["Unicode"] @@ -311,9 +311,9 @@ version = "2.3.1" [[deps.StaticArrays]] deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] -git-tree-sha1 = "7b0e9c14c624e435076d19aea1e5cbdec2b9ca37" +git-tree-sha1 = "bf074c045d3d5ffd956fa0a461da38a44685d6b2" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.9.2" +version = "1.9.3" [deps.StaticArrays.extensions] StaticArraysChainRulesCoreExt = "ChainRulesCore" diff --git a/dev/developers/contributing/index.html b/dev/developers/contributing/index.html index 942736c..951fdc0 100644 --- a/dev/developers/contributing/index.html +++ b/dev/developers/contributing/index.html @@ -1,49 +1,56 @@ Contributing · LinearElasticityBase.jl

Contributing

Welcome! This document explains some ways you can contribute to LinearElasticityBase.

Code of conduct

This project and everyone participating in it is governed by the "Contributor Covenant Code of Conduct". By participating, you are expected to uphold this code.

Join the community forum

First up, join the community forum.

The forum is a good place to ask questions about how to use LinearElasticityBase. You can also use the forum to discuss possible feature requests and bugs before raising a GitHub issue (more on this below).

Aside from asking questions, the easiest way you can contribute to LinearElasticityBase is to help answer questions on the forum!

Improve the documentation

Chances are, if you asked (or answered) a question on the community forum, then it is a sign that the documentation could be improved. Moreover, since it is your question, you are probably the best-placed person to improve it!

The docs are written in Markdown and are built using Documenter.jl. You can find the source of all the docs here.

If your change is small (like fixing typos, or one or two sentence corrections), the easiest way to do this is via GitHub's online editor. (GitHub has help on how to do this.)

If your change is larger, or touches multiple files, you will need to make the change locally and then use Git to submit a pull request. (See Contribute code to LinearElasticityBase below for more on this.)

File a bug report

Another way to contribute to LinearElasticityBase is to file bug reports.

Make sure you read the info in the box where you write the body of the issue before posting. You can also find a copy of that info here.

Tip

If you're unsure whether you have a real bug, post on the community forum first. Someone will either help you fix the problem, or let you know the most appropriate place to open a bug report.

Contribute code to LinearElasticityBase

Finally, you can also contribute code to LinearElasticityBase!

Warning

If you do not have experience with Git, GitHub, and Julia development, the first steps can be a little daunting. However, there are lots of tutorials available online, including:

Once you are familiar with Git and GitHub, the workflow for contributing code to LinearElasticityBase is similar to the following:

Step 1: decide what to work on

The first step is to find an open issue (or open a new one) for the problem you want to solve. Then, before spending too much time on it, discuss what you are planning to do in the issue to see if other contributors are fine with your proposed changes. Getting feedback early can improve code quality, and avoid time spent writing code that does not get merged into LinearElasticityBase.

Tip

At this point, remember to be patient and polite; you may get a lot of comments on your issue! However, do not be afraid! Comments mean that people are willing to help you improve the code that you are contributing to LinearElasticityBase.

Step 2: fork LinearElasticityBase

Go to https://github.com/MineralsCloud/LinearElasticityBase.jl and click the "Fork" button in the top-right corner. This will create a copy of LinearElasticityBase under your GitHub account.

Step 3: install LinearElasticityBase locally

Similar to Installation, open the Julia REPL and run:

julia> using Pkg
julia> Pkg.update() Updating registry at `~/.julia/registries/General.toml` + Installed IOCapture ─────────────── v0.2.4 + Installed OpenSSL_jll ───────────── v3.0.13+1 + Installed Expat_jll ─────────────── v2.5.0+0 Installed RegistryInstances ─────── v0.1.0 Installed Libiconv_jll ──────────── v1.17.0+0 - Installed IOCapture ─────────────── v0.2.4 + Installed Git_jll ───────────────── v2.44.0+2 + Installed CodecZlib ─────────────── v0.7.4 + Installed Git ───────────────────── v1.3.1 Installed MarkdownAST ───────────── v0.1.2 - Installed Git_jll ───────────────── v2.43.0+0 - Installed Expat_jll ─────────────── v2.5.0+0 - Installed OpenSSL_jll ───────────── v3.0.13+0 - Installed AbstractTrees ─────────── v0.4.4 - Installed Git ───────────────────── v1.3.0 + Installed TranscodingStreams ────── v0.10.7 Installed LazilyInitializedFields ─ v1.2.2 - Installed Documenter ────────────── v1.2.1 + Installed AbstractTrees ─────────── v0.4.5 + Installed Documenter ────────────── v1.3.0 Updating `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/Project.toml` - [e30172f5] ↑ Documenter v0.27.24 ⇒ v1.2.1 + [e30172f5] ↑ Documenter v0.27.24 ⇒ v1.3.0 Updating `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/Manifest.toml` - [1520ce14] + AbstractTrees v0.4.4 - [e30172f5] ↑ Documenter v0.27.24 ⇒ v1.2.1 - [d7ba0133] + Git v1.3.0 + [1520ce14] + AbstractTrees v0.4.5 + [944b1d66] + CodecZlib v0.7.4 + [e30172f5] ↑ Documenter v0.27.24 ⇒ v1.3.0 + [d7ba0133] + Git v1.3.1 [b5f81e59] ↑ IOCapture v0.2.2 ⇒ v0.2.4 [682c06a0] ↑ JSON v0.21.3 ⇒ v0.21.4 [0e77f7df] + LazilyInitializedFields v1.2.2 [d0879d2d] + MarkdownAST v0.1.2 [69de0a69] ↑ Parsers v2.5.4 ⇒ v2.8.1 - [21216c6a] ↑ Preferences v1.3.0 ⇒ v1.4.1 + [21216c6a] ↑ Preferences v1.3.0 ⇒ v1.4.3 [2792f1a3] + RegistryInstances v0.1.0 [66db9d55] - SnoopPrecompile v1.0.3 + [3bb67fe8] + TranscodingStreams v0.10.7 [2e619515] + Expat_jll v2.5.0+0 - [f8c6e375] + Git_jll v2.43.0+0 + [f8c6e375] + Git_jll v2.44.0+2 [94ce4f54] + Libiconv_jll v1.17.0+0 - [458c3c95] + OpenSSL_jll v3.0.13+0 + [458c3c95] + OpenSSL_jll v3.0.13+1 [efcefdf7] + PCRE2_jll v10.42.0+1 Precompiling project... -IOCapture -LazilyInitializedFields -AbstractTrees -RegistryInstances -OpenSSL_jll -Expat_jll -Libiconv_jll -MarkdownAST -Git_jll -Git -Documenter - 11 dependencies successfully precompiled in 22 seconds. 34 already precompiled. - 2 dependencies precompiled but different versions are currently loaded. Restart julia to access the new versions + ✓ LazilyInitializedFields + ✓ IOCapture + ✓ AbstractTrees + ✓ TranscodingStreams + ✓ Libiconv_jll + ✓ Expat_jll + ✓ OpenSSL_jll + ✓ RegistryInstances + ✓ MarkdownAST + ✓ TranscodingStreams → TestExt + ✓ Git_jll + ✓ CodecZlib + ✓ Git + ✓ Documenter + 14 dependencies successfully precompiled in 24 seconds. 34 already precompiled. + 2 dependencies precompiled but different versions are currently loaded. Restart julia to access the new versions Info We haven't cleaned this depot up for a bit, running Pkg.gc()... Active manifest files: 3 found Active artifact files: 5 found @@ -54,9 +61,9 @@ [c9ccf908] ~ LinearElasticityBase v0.3.0 `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl` ⇒ v0.3.0 `~/.julia/dev/LinearElasticityBase` Updating `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/Manifest.toml` [c9ccf908] ~ LinearElasticityBase v0.3.0 `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl` ⇒ v0.3.0 `~/.julia/dev/LinearElasticityBase`

Then the package will be cloned to your local machine. On *nix systems, the default path is ~/.julia/dev/LinearElasticityBase unless you modify the JULIA_DEPOT_PATH environment variable. If you're on Windows, this will be C:\\Users\\<my_name>\\.julia\\dev\\LinearElasticityBase. In the following text, we will call it PKGROOT.

Go to PKGROOT, start a new Julia session and run

julia> using Pkg
julia> Pkg.instantiate()Precompiling project... -LinearElasticityBase - 1 dependency successfully precompiled in 17 seconds. 44 already precompiled. - 1 dependency precompiled but a different version is currently loaded. Restart julia to access the new version

to instantiate the project.

Step 4: checkout a new branch

Note

In the following, replace any instance of GITHUB_ACCOUNT with your GitHub username.

The next step is to checkout a development branch. In a terminal (or command prompt on Windows), run:

cd ~/.julia/dev/LinearElasticityBase
+  ✓ LinearElasticityBase
+  1 dependency successfully precompiled in 18 seconds. 47 already precompiled.
+  1 dependency precompiled but a different version is currently loaded. Restart julia to access the new version

to instantiate the project.

Step 4: checkout a new branch

Note

In the following, replace any instance of GITHUB_ACCOUNT with your GitHub username.

The next step is to checkout a development branch. In a terminal (or command prompt on Windows), run:

cd ~/.julia/dev/LinearElasticityBase
 
 git remote add GITHUB_ACCOUNT https://github.com/GITHUB_ACCOUNT/LinearElasticityBase.jl.git
 
@@ -74,4 +81,4 @@
 
 git checkout main
 
-git pull
Note

If you have suggestions to improve this guide, please make a pull request! It's particularly helpful if you do this after your first pull request because you'll know all the parts that could be explained better.

Thanks for contributing to LinearElasticityBase!

+git pull
Note

If you have suggestions to improve this guide, please make a pull request! It's particularly helpful if you do this after your first pull request because you'll know all the parts that could be explained better.

Thanks for contributing to LinearElasticityBase!

diff --git a/dev/developers/design-principles/index.html b/dev/developers/design-principles/index.html index 8de91a6..8b7547e 100644 --- a/dev/developers/design-principles/index.html +++ b/dev/developers/design-principles/index.html @@ -13,4 +13,4 @@ end return y end

and thus using such a macro as the interface is not preferred when possible. However, a macro like @muladd is trivial to picture on a code (it recursively transforms a*b + c to muladd(a,b,c) for more accuracy and efficiency), so using such a macro for example:

julia> @macroexpand(@muladd k3 = f(t + c3 * dt, @. uprev + dt * (a031 * k1 + a032 * k2)))
-:(k3 = f((muladd)(c3, dt, t), (muladd).(dt, (muladd).(a032, k2, (*).(a031, k1)), uprev)))

is recommended. Some macros in this category are:

Some performance macros, like @simd, @threads, or @turbo from LoopVectorization.jl, make an exception in that their generated code may be foreign to many users. However, they still are classified as appropriate uses as they are syntactic sugar since they do (or should) not change the behavior of the program in measurable ways other than performance.

Errors should be caught as high as possible, and error messages should be contextualized for newcomers

Whenever possible, defensive programming should be used to check for potential errors before they are encountered deeper within a package. For example, if one knows that f(u0,p) will error unless u0 is the size of p, this should be caught at the start of the function to throw a domain specific error, for example "parameters and initial condition should be the same size".

Subpackaging and interface packages is preferred over conditional modules via Requires.jl

Requires.jl should be avoided at all costs. If an interface package exists, such as ChainRulesCore.jl for defining automatic differentiation rules without requiring a dependency on the whole ChainRules.jl system, or RecipesBase.jl which allows for defining Plots.jl plot recipes without a dependency on Plots.jl, a direct dependency on these interface packages is preferred.

Otherwise, instead of resorting to a conditional dependency using Requires.jl, it is preferred one creates subpackages, i.e. smaller independent packages kept within the same Github repository with independent versioning and package management. An example of this is seen in Optimization.jl which has subpackages like OptimizationBBO.jl for BlackBoxOptim.jl support.

Some important interface packages to know about are:

Functions should either attempt to be non-allocating and reuse caches, or treat inputs as immutable

Mutating codes and non-mutating codes fall into different worlds. When a code is fully immutable, the compiler can better reason about dependencies, optimize the code, and check for correctness. However, many times a code making the fullest use of mutation can outperform even what the best compilers of today can generate. That said, the worst of all worlds is when code mixes mutation with non-mutating code. Not only is this a mishmash of coding styles, it has the potential non-locality and compiler proof issues of mutating code while not fully benefiting from the mutation.

Out-Of-Place and Immutability is preferred when sufficient performant

Mutation is used to get more performance by decreasing the amount of heap allocations. However, if it's not helpful for heap allocations in a given spot, do not use mutation. Mutation is scary and should be avoided unless it gives an immediate benefit. For example, if matrices are sufficiently large, then A*B is as fast as mul!(C,A,B), and thus writing A*B is preferred (unless the rest of the function is being careful about being fully non-allocating, in which case this should be mul! for consistency).

Similarly, when defining types, using struct is preferred to mutable struct unless mutating the struct is a common occurrence. Even if mutating the struct is a common occurrence, see whether using Setfield.jl is sufficient. The compiler will optimize the construction of immutable structs, and thus this can be more efficient if it's not too much of a code hassle.

Tests should attempt to cover a wide gamut of input types

Code coverage numbers are meaningless if one does not consider the input types. For example, one can hit all the code with Array, but that does not test whether CuArray is compatible! Thus, it's always good to think of coverage not in terms of lines of code but in terms of type coverage. A good list of number types to think about are:

Array types to think about testing are:

When in doubt, a submodule should become a subpackage or separate package

Keep packages to one core idea. If there's something separate enough to be a submodule, could it instead be a separate well-tested and documented package to be used by other packages? Most likely yes.

Globals should be avoided whenever possible

Global variables should be avoided whenever possible. When required, global variables should be constants and have an all uppercase name separated with underscores (e.g. MY_CONSTANT). They should be defined at the top of the file, immediately after imports and exports but before an __init__ function. If you truly want mutable global style behavior you may want to look into mutable containers.

Type-stable and Type-grounded code is preferred wherever possible

Type-stable and type-grounded code helps the compiler create not only more optimized code, but also faster to compile code. Always keep containers well-typed, functions specializing on the appropriate arguments, and types concrete.

Closures should be avoided whenever possible

Closures can cause accidental type instabilities that are difficult to track down and debug; in the long run it saves time to always program defensively and avoid writing closures in the first place, even when a particular closure would not have been problematic. A similar argument applies to reading code with closures; if someone is looking for type instabilities, this is faster to do when code does not contain closures. Furthermore, if you want to update variables in an outer scope, do so explicitly with Refs or self defined structs. For example,

map(Base.Fix2(getindex, i), vector_of_vectors)

is preferred over

map(v -> v[i], vector_of_vectors)

or

[v[i] for v in vector_of_vectors]

Numerical functionality should use the appropriate generic numerical interfaces

While you can use A\b to do a linear solve inside a package, that does not mean that you should. This interface is only sufficient for performing factorizations, and so that limits the scaling choices, the types of A that can be supported, etc. Instead, linear solves within packages should use LinearSolve.jl. Similarly, nonlinear solves should use NonlinearSolve.jl. Optimization should use Optimization.jl. Etc. This allows the full generic choice to be given to the user without depending on every solver package (effectively recreating the generic interfaces within each package).

Functions should capture one underlying principle

Functions mean one thing. Every dispatch of + should be "the meaning of addition on these types". While in theory you could add dispatches to + that mean something different, that will fail in generic code for which + means addition. Thus, for generic code to work, code needs to adhere to one meaning for each function. Every dispatch should be an instantiation of that meaning.

Internal choices should be exposed as options whenever possible

Whenever possible, numerical values and choices within scripts should be exposed as options to the user. This promotes code reusability beyond the few cases the author may have expected.

Prefer code reuse over rewrites whenever possible

If a package has a function you need, use the package. Add a dependency if you need to. If the function is missing a feature, prefer to add that feature to said package and then add it as a dependency. If the dependency is potentially troublesome, for example because it has a high load time, prefer to spend time helping said package fix these issues and add the dependency. Only when it does not seem possible to make the package "good enough" should using the package be abandoned. If it is abandoned, consider building a new package for this functionality as you need it, and then make it a dependency.

Prefer to not shadow functions

Two functions can have the same name in Julia by having different namespaces. For example, X.f and Y.f can be two different functions, with different dispatches, but the same name. This should be avoided whenever possible. Instead of creating MyPackage.sort, consider adding dispatches to Base.sort for your types if these new dispatches match the underlying principle of the function. If it doesn't, prefer to use a different name. While using MyPackage.sort is not conflicting, it is going to be confusing for most people unfamiliar with your code, so MyPackage.special_sort would be more helpful to newcomers reading the code.

+:(k3 = f((muladd)(c3, dt, t), (muladd).(dt, (muladd).(a032, k2, (*).(a031, k1)), uprev)))

is recommended. Some macros in this category are:

Some performance macros, like @simd, @threads, or @turbo from LoopVectorization.jl, make an exception in that their generated code may be foreign to many users. However, they still are classified as appropriate uses as they are syntactic sugar since they do (or should) not change the behavior of the program in measurable ways other than performance.

Errors should be caught as high as possible, and error messages should be contextualized for newcomers

Whenever possible, defensive programming should be used to check for potential errors before they are encountered deeper within a package. For example, if one knows that f(u0,p) will error unless u0 is the size of p, this should be caught at the start of the function to throw a domain specific error, for example "parameters and initial condition should be the same size".

Subpackaging and interface packages is preferred over conditional modules via Requires.jl

Requires.jl should be avoided at all costs. If an interface package exists, such as ChainRulesCore.jl for defining automatic differentiation rules without requiring a dependency on the whole ChainRules.jl system, or RecipesBase.jl which allows for defining Plots.jl plot recipes without a dependency on Plots.jl, a direct dependency on these interface packages is preferred.

Otherwise, instead of resorting to a conditional dependency using Requires.jl, it is preferred one creates subpackages, i.e. smaller independent packages kept within the same Github repository with independent versioning and package management. An example of this is seen in Optimization.jl which has subpackages like OptimizationBBO.jl for BlackBoxOptim.jl support.

Some important interface packages to know about are:

Functions should either attempt to be non-allocating and reuse caches, or treat inputs as immutable

Mutating codes and non-mutating codes fall into different worlds. When a code is fully immutable, the compiler can better reason about dependencies, optimize the code, and check for correctness. However, many times a code making the fullest use of mutation can outperform even what the best compilers of today can generate. That said, the worst of all worlds is when code mixes mutation with non-mutating code. Not only is this a mishmash of coding styles, it has the potential non-locality and compiler proof issues of mutating code while not fully benefiting from the mutation.

Out-Of-Place and Immutability is preferred when sufficient performant

Mutation is used to get more performance by decreasing the amount of heap allocations. However, if it's not helpful for heap allocations in a given spot, do not use mutation. Mutation is scary and should be avoided unless it gives an immediate benefit. For example, if matrices are sufficiently large, then A*B is as fast as mul!(C,A,B), and thus writing A*B is preferred (unless the rest of the function is being careful about being fully non-allocating, in which case this should be mul! for consistency).

Similarly, when defining types, using struct is preferred to mutable struct unless mutating the struct is a common occurrence. Even if mutating the struct is a common occurrence, see whether using Setfield.jl is sufficient. The compiler will optimize the construction of immutable structs, and thus this can be more efficient if it's not too much of a code hassle.

Tests should attempt to cover a wide gamut of input types

Code coverage numbers are meaningless if one does not consider the input types. For example, one can hit all the code with Array, but that does not test whether CuArray is compatible! Thus, it's always good to think of coverage not in terms of lines of code but in terms of type coverage. A good list of number types to think about are:

Array types to think about testing are:

When in doubt, a submodule should become a subpackage or separate package

Keep packages to one core idea. If there's something separate enough to be a submodule, could it instead be a separate well-tested and documented package to be used by other packages? Most likely yes.

Globals should be avoided whenever possible

Global variables should be avoided whenever possible. When required, global variables should be constants and have an all uppercase name separated with underscores (e.g. MY_CONSTANT). They should be defined at the top of the file, immediately after imports and exports but before an __init__ function. If you truly want mutable global style behavior you may want to look into mutable containers.

Type-stable and Type-grounded code is preferred wherever possible

Type-stable and type-grounded code helps the compiler create not only more optimized code, but also faster to compile code. Always keep containers well-typed, functions specializing on the appropriate arguments, and types concrete.

Closures should be avoided whenever possible

Closures can cause accidental type instabilities that are difficult to track down and debug; in the long run it saves time to always program defensively and avoid writing closures in the first place, even when a particular closure would not have been problematic. A similar argument applies to reading code with closures; if someone is looking for type instabilities, this is faster to do when code does not contain closures. Furthermore, if you want to update variables in an outer scope, do so explicitly with Refs or self defined structs. For example,

map(Base.Fix2(getindex, i), vector_of_vectors)

is preferred over

map(v -> v[i], vector_of_vectors)

or

[v[i] for v in vector_of_vectors]

Numerical functionality should use the appropriate generic numerical interfaces

While you can use A\b to do a linear solve inside a package, that does not mean that you should. This interface is only sufficient for performing factorizations, and so that limits the scaling choices, the types of A that can be supported, etc. Instead, linear solves within packages should use LinearSolve.jl. Similarly, nonlinear solves should use NonlinearSolve.jl. Optimization should use Optimization.jl. Etc. This allows the full generic choice to be given to the user without depending on every solver package (effectively recreating the generic interfaces within each package).

Functions should capture one underlying principle

Functions mean one thing. Every dispatch of + should be "the meaning of addition on these types". While in theory you could add dispatches to + that mean something different, that will fail in generic code for which + means addition. Thus, for generic code to work, code needs to adhere to one meaning for each function. Every dispatch should be an instantiation of that meaning.

Internal choices should be exposed as options whenever possible

Whenever possible, numerical values and choices within scripts should be exposed as options to the user. This promotes code reusability beyond the few cases the author may have expected.

Prefer code reuse over rewrites whenever possible

If a package has a function you need, use the package. Add a dependency if you need to. If the function is missing a feature, prefer to add that feature to said package and then add it as a dependency. If the dependency is potentially troublesome, for example because it has a high load time, prefer to spend time helping said package fix these issues and add the dependency. Only when it does not seem possible to make the package "good enough" should using the package be abandoned. If it is abandoned, consider building a new package for this functionality as you need it, and then make it a dependency.

Prefer to not shadow functions

Two functions can have the same name in Julia by having different namespaces. For example, X.f and Y.f can be two different functions, with different dispatches, but the same name. This should be avoided whenever possible. Instead of creating MyPackage.sort, consider adding dispatches to Base.sort for your types if these new dispatches match the underlying principle of the function. If it doesn't, prefer to use a different name. While using MyPackage.sort is not conflicting, it is going to be confusing for most people unfamiliar with your code, so MyPackage.special_sort would be more helpful to newcomers reading the code.

diff --git a/dev/developers/style-guide/index.html b/dev/developers/style-guide/index.html index b812069..38c29ad 100644 --- a/dev/developers/style-guide/index.html +++ b/dev/developers/style-guide/index.html @@ -1,29 +1,29 @@ Style Guide · LinearElasticityBase.jl

Style Guide

    This section describes the coding style rules that apply to our code and that we recommend you to use it also.

    In some cases, our style guide diverges from Julia's official Style Guide (Please read it!). All such cases will be explicitly noted and justified.

    Our style guide adopts many recommendations from the BlueStyle. Please read the BlueStyle before contributing to this package. If not following, your pull requests may not be accepted.

    Info

    The style guide is always a work in progress, and not all LinearElasticityBase code follows the rules. When modifying LinearElasticityBase, please fix the style violations of the surrounding code (i.e., leave the code tidier than when you started). If large changes are needed, consider separating them into another pull request.

    Formatting

    Run JuliaFormatter

    LinearElasticityBase uses JuliaFormatter as an auto-formatting tool.

    We use the options contained in .JuliaFormatter.toml.

    To format your code, cd to the LinearElasticityBase directory, then run:

    julia> using Pkg
    julia> Pkg.add("JuliaFormatter") Resolving package versions... Installed Crayons ──────────── v4.1.1 + Installed CSTParser ────────── v3.4.2 + Installed Tokenize ─────────── v0.5.28 + Installed OrderedCollections ─ v1.6.3 Installed URIs ─────────────── v1.5.1 - Installed CSTParser ────────── v3.4.1 Installed Glob ─────────────── v1.3.1 - Installed Tokenize ─────────── v0.5.28 - Installed DataStructures ───── v0.18.16 + Installed DataStructures ───── v0.18.18 Installed CommonMark ───────── v0.8.12 - Installed JuliaFormatter ───── v1.0.45 - Installed OrderedCollections ─ v1.6.3 + Installed JuliaFormatter ───── v1.0.56 Updating `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/build/developers/Project.toml` - [98e50ef6] + JuliaFormatter v1.0.45 + [98e50ef6] + JuliaFormatter v1.0.56 Updating `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/build/developers/Manifest.toml` - [00ebfdb7] + CSTParser v3.4.1 + [00ebfdb7] + CSTParser v3.4.2 [a80b9123] + CommonMark v0.8.12 - [34da2185] + Compat v4.12.0 + [34da2185] + Compat v4.14.0 [a8cc5b0e] + Crayons v4.1.1 - [864edb3b] + DataStructures v0.18.16 + [864edb3b] + DataStructures v0.18.18 [c27321d9] + Glob v1.3.1 [682c06a0] + JSON v0.21.4 - [98e50ef6] + JuliaFormatter v1.0.45 + [98e50ef6] + JuliaFormatter v1.0.56 [bac558e1] + OrderedCollections v1.6.3 [69de0a69] + Parsers v2.8.1 - [aea7be01] + PrecompileTools v1.2.0 - [21216c6a] + Preferences v1.4.1 + [aea7be01] + PrecompileTools v1.2.1 + [21216c6a] + Preferences v1.4.3 [0796e94c] + Tokenize v0.5.28 [5c2747f8] + URIs v1.5.1 [0dad84c5] + ArgTools v1.1.1 @@ -60,18 +60,18 @@ [8e850ede] + nghttp2_jll v1.52.0+1 [3f19e933] + p7zip_jll v17.4.0+2 Precompiling project... -Glob -OrderedCollections -URIs -Crayons -DataStructures -Tokenize -CSTParser -CommonMark -JuliaFormatter - 9 dependencies successfully precompiled in 25 seconds. 7 already precompiled.
    julia> using JuliaFormatter: format┌ Warning: Module JSON with build ID fafbfcfd-f8e7-cc32-0000-00177fd2bb48 is missing from the cache. + ✓ Glob + ✓ OrderedCollections + ✓ URIs + ✓ Crayons + ✓ DataStructures + ✓ Tokenize + ✓ CSTParser + ✓ CommonMark + ✓ JuliaFormatter + 9 dependencies successfully precompiled in 27 seconds. 7 already precompiled.
    julia> using JuliaFormatter: format┌ Warning: Module JSON with build ID fafbfcfd-0cc5-246e-0000-0036ae9a8478 is missing from the cache. This may mean JSON [682c06a0-de6a-54ab-a142-c8b1cf79cde6] does not support precompilation but is imported by a module that does. -@ Base loading.jl:1942 -┌ Warning: Module JSON with build ID fafbfcfd-f8e7-cc32-0000-00177fd2bb48 is missing from the cache. +@ Base loading.jl:1948 +┌ Warning: Module JSON with build ID fafbfcfd-0cc5-246e-0000-0036ae9a8478 is missing from the cache. This may mean JSON [682c06a0-de6a-54ab-a142-c8b1cf79cde6] does not support precompilation but is imported by a module that does. -@ Base loading.jl:1942
    julia> format("docs");ERROR: IOError: realpath("docs"): no such file or directory (ENOENT)
    julia> format("src");ERROR: IOError: realpath("src"): no such file or directory (ENOENT)
    julia> format("test");ERROR: IOError: realpath("test"): no such file or directory (ENOENT)
    Info

    A continuous integration check verifies that all PRs made to LinearElasticityBase have passed the formatter.

    The following sections outline extra style guide points that are not fixed automatically by JuliaFormatter.

    Use the Julia extension for Visual Studio Code

    Please use VS Code with the Julia extension to edit, format, and test your code. We do not recommend using other editors to edit your code for the time being.

    This extension already has JuliaFormatter integrated. So to format your code, follow the steps listed here.

    +@ Base loading.jl:1948
    julia> format("docs");ERROR: IOError: realpath("docs"): no such file or directory (ENOENT)
    julia> format("src");ERROR: IOError: realpath("src"): no such file or directory (ENOENT)
    julia> format("test");ERROR: IOError: realpath("test"): no such file or directory (ENOENT)
    Info

    A continuous integration check verifies that all PRs made to LinearElasticityBase have passed the formatter.

    The following sections outline extra style guide points that are not fixed automatically by JuliaFormatter.

    Use the Julia extension for Visual Studio Code

    Please use VS Code with the Julia extension to edit, format, and test your code. We do not recommend using other editors to edit your code for the time being.

    This extension already has JuliaFormatter integrated. So to format your code, follow the steps listed here.

    diff --git a/dev/index.html b/dev/index.html index 4ac7d07..8785382 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,7 +1,7 @@ Home · LinearElasticityBase.jl

    LinearElasticityBase

    Documentation for LinearElasticityBase.

    See the Index for the complete list of documented functions and types.

    The code is hosted on GitHub, with some continuous integration services to test its validity.

    This repository is created and maintained by @singularitti. You are very welcome to contribute.

    Installation

    The package can be installed with the Julia package manager. From the Julia REPL, type ] to enter the Pkg REPL mode and run:

    pkg> add LinearElasticityBase

    Or, equivalently, via the Pkg API:

    julia> import Pkg; Pkg.add("LinearElasticityBase")   Resolving package versions...
    -   Installed LinearElasticityBase ─ v0.3.0
        Installed Tensorial ──────────── v0.12.19
    +   Installed LinearElasticityBase ─ v0.3.0
         Updating `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/build/developers/Project.toml`
       [c9ccf908] + LinearElasticityBase v0.3.0
         Updating `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/build/developers/Manifest.toml`
    @@ -14,11 +14,11 @@
       [92d709cd] + IrrationalConstants v0.2.2
       [692b3bcd] + JLLWrappers v1.5.0
       [c9ccf908] + LinearElasticityBase v0.3.0
    -  [2ab3a3ac] + LogExpFunctions v0.3.26
    +  [2ab3a3ac] + LogExpFunctions v0.3.27
       [1914dd2f] + MacroTools v0.5.13
       [77ba4419] + NaNMath v1.0.2
       [276daf66] + SpecialFunctions v2.3.1
    -  [90137ffa] + StaticArrays v1.9.2
    +  [90137ffa] + StaticArrays v1.9.3
       [1e83bf80] + StaticArraysCore v1.4.2
     ⌅ [98f94333] + Tensorial v0.12.19
       [efe28fd5] + OpenSpecFun_jll v0.5.5+0
    @@ -26,14 +26,14 @@
       [2f01184e] + SparseArrays v1.10.0
       [10745b16] + Statistics v1.10.0
       [8dfed614] + Test
    -  [e66e0078] + CompilerSupportLibraries_jll v1.0.5+1
    -  [4536629a] + OpenBLAS_jll v0.3.23+2
    +  [e66e0078] + CompilerSupportLibraries_jll v1.1.0+0
    +  [4536629a] + OpenBLAS_jll v0.3.23+4
       [05823500] + OpenLibm_jll v0.8.1+2
       [bea87d4a] + SuiteSparse_jll v7.2.1+1
       [8e850b90] + libblastrampoline_jll v5.8.0+1
             Info Packages marked with ⌅ have new versions available but compatibility constraints restrict them from upgrading. To see why use `status --outdated -m`
     Precompiling project...
    -Tensorial
    -LinearElasticityBase
    +  ✓ Tensorial
    +  ✓ LinearElasticityBase
       2 dependencies successfully precompiled in 3 seconds. 39 already precompiled.
    -  2 dependencies precompiled but different versions are currently loaded. Restart julia to access the new versions

    Documentation

    • STABLEdocumentation of the most recently tagged version.
    • DEVdocumentation of the in-development version.

    Project status

    The package is tested against, and being developed for, Julia 1.6 and above on Linux, macOS, and Windows.

    Questions and contributions

    Usage questions can be posted on our discussion page.

    Contributions are very welcome, as are feature requests and suggestions. Please open an issue if you encounter any problems. The Contributing page has a few guidelines that should be followed when opening pull requests and contributing code.

    Manual outline

    Library outline

      Index

        + 2 dependencies precompiled but different versions are currently loaded. Restart julia to access the new versions

        Documentation

        Project status

        The package is tested against, and being developed for, Julia 1.6 and above on Linux, macOS, and Windows.

        Questions and contributions

        Usage questions can be posted on our discussion page.

        Contributions are very welcome, as are feature requests and suggestions. Please open an issue if you encounter any problems. The Contributing page has a few guidelines that should be followed when opening pull requests and contributing code.

        Manual outline

        Library outline

        Index

        diff --git a/dev/installation/index.html b/dev/installation/index.html index 579a0a5..c756b48 100644 --- a/dev/installation/index.html +++ b/dev/installation/index.html @@ -7,7 +7,7 @@ julia> Pkg.add("LinearElasticityBase")
      • Run

        julia> using LinearElasticityBase

        and have fun!

      • While using, please keep this Julia session alive. Restarting might cost some time.

      • If you want to install the latest in-development (probably buggy) version of LinearElasticityBase, type

        julia> using Pkg
        julia> Pkg.update() Updating registry at `~/.julia/registries/General.toml` No Changes to `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/build/developers/Project.toml` No Changes to `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/build/developers/Manifest.toml`
        julia> pkg"add https://github.com/MineralsCloud/LinearElasticityBase.jl"┌ Warning: The Pkg REPL mode is intended for interactive use only, and should not be used from scripts. It is recommended to use the functional API instead. -└ @ Pkg.REPLMode /opt/hostedtoolcache/julia/1.10.0/x64/share/julia/stdlib/v1.10/Pkg/src/REPLMode/REPLMode.jl:382 +└ @ Pkg.REPLMode /opt/hostedtoolcache/julia/1.10.2/x64/share/julia/stdlib/v1.10/Pkg/src/REPLMode/REPLMode.jl:382 Cloning git-repo `https://github.com/MineralsCloud/LinearElasticityBase.jl` Updating git-repo `https://github.com/MineralsCloud/LinearElasticityBase.jl` Resolving package versions... @@ -16,9 +16,9 @@ Updating `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/build/developers/Manifest.toml` [c9ccf908] ~ LinearElasticityBase v0.3.0 ⇒ v0.3.0 `https://github.com/MineralsCloud/LinearElasticityBase.jl#main` Precompiling project... -LinearElasticityBase + ✓ LinearElasticityBase 1 dependency successfully precompiled in 1 seconds. 40 already precompiled. - 1 dependency precompiled but a different version is currently loaded. Restart julia to access the new version

        in the second step above.

        Update LinearElasticityBase

        Please watch our GitHub repository for new releases. Once we release a new version, you can update LinearElasticityBase by typing

        julia> using Pkg
        julia> Pkg.update("LinearElasticityBase") Updating registry at `~/.julia/registries/General.toml` + 1 dependency precompiled but a different version is currently loaded. Restart julia to access the new version

        in the second step above.

        Update LinearElasticityBase

        Please watch our GitHub repository for new releases. Once we release a new version, you can update LinearElasticityBase by typing

        julia> using Pkg
        julia> Pkg.update("LinearElasticityBase") Updating registry at `~/.julia/registries/General.toml` Updating git-repo `https://github.com/MineralsCloud/LinearElasticityBase.jl` No Changes to `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/build/developers/Project.toml` No Changes to `~/work/LinearElasticityBase.jl/LinearElasticityBase.jl/docs/build/developers/Manifest.toml`
        julia> Pkg.gc() Active manifest files: 4 found @@ -28,4 +28,4 @@ julia> Pkg.rm("LinearElasticityBase") -julia> Pkg.gc()
      • Press ctrl+d to quit the current session. Start a new Julia session and reinstall LinearElasticityBase.

      • +julia> Pkg.gc()
      • Press ctrl+d to quit the current session. Start a new Julia session and reinstall LinearElasticityBase.

      • diff --git a/dev/search/index.html b/dev/search/index.html index 30e3c82..dc2d4d8 100644 --- a/dev/search/index.html +++ b/dev/search/index.html @@ -1,2 +1,2 @@ -Search · LinearElasticityBase.jl

        Loading search...

          +Search · LinearElasticityBase.jl

          Loading search...

            diff --git a/dev/troubleshooting/index.html b/dev/troubleshooting/index.html index d93381f..02b9405 100644 --- a/dev/troubleshooting/index.html +++ b/dev/troubleshooting/index.html @@ -1,2 +1,2 @@ -Troubleshooting · LinearElasticityBase.jl

            Troubleshooting

            This page collects some possible errors you may encounter and trick how to fix them. If you have some questions about how to use this code, you are welcome to discuss with us.

            If you have additional tips, please either report an issue or submit a PR with suggestions.

            Installation problems

            Cannot find the julia executable

            Make sure you have Julia installed in your environment. Please download the latest stable version for your platform. If you are using a *nix system, the recommended way is to use Juliaup. If you do not want to install Juliaup or you are using other platforms that Julia supports, download the corresponding binaries. Then, create a symbolic link to the Julia executable. If the path is not in your $PATH environment variable, export it to your $PATH.

            Some clusters, like Habanero, Comet, or Expanse, already have Julia installed as a module, you may just module load julia to use it. If not, either install by yourself or contact your administrator.

            Loading LinearElasticityBase

            Julia compiles/loads slow

            First, we recommend you download the latest version of Julia. Usually, the newest version has the best performance.

            If you just want Julia to do a simple task and only once, you could start the Julia REPL with

            julia --compile=min

            to minimize compilation or

            julia --optimize=0

            to minimize optimizations, or just use both. Or you could make a system image and run with

            julia --sysimage custom-image.so

            See Fredrik Ekre's talk for details.

            +Troubleshooting · LinearElasticityBase.jl

            Troubleshooting

            This page collects some possible errors you may encounter and trick how to fix them. If you have some questions about how to use this code, you are welcome to discuss with us.

            If you have additional tips, please either report an issue or submit a PR with suggestions.

            Installation problems

            Cannot find the julia executable

            Make sure you have Julia installed in your environment. Please download the latest stable version for your platform. If you are using a *nix system, the recommended way is to use Juliaup. If you do not want to install Juliaup or you are using other platforms that Julia supports, download the corresponding binaries. Then, create a symbolic link to the Julia executable. If the path is not in your $PATH environment variable, export it to your $PATH.

            Some clusters, like Habanero, Comet, or Expanse, already have Julia installed as a module, you may just module load julia to use it. If not, either install by yourself or contact your administrator.

            Loading LinearElasticityBase

            Julia compiles/loads slow

            First, we recommend you download the latest version of Julia. Usually, the newest version has the best performance.

            If you just want Julia to do a simple task and only once, you could start the Julia REPL with

            julia --compile=min

            to minimize compilation or

            julia --optimize=0

            to minimize optimizations, or just use both. Or you could make a system image and run with

            julia --sysimage custom-image.so

            See Fredrik Ekre's talk for details.