diff --git a/LocalPreferences.toml b/LocalPreferences.toml new file mode 100644 index 0000000..f846147 --- /dev/null +++ b/LocalPreferences.toml @@ -0,0 +1,2 @@ +[CUDA] +default_memory ="unified" \ No newline at end of file diff --git a/Manifest.toml b/Manifest.toml index bab735c..adc4146 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -1,8 +1,8 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.9.2" +julia_version = "1.10.1" manifest_format = "2.0" -project_hash = "c304988b52185de8c78ceac3fd70682c20ef08f1" +project_hash = "6eb75216c6042b842062963037ad619f676b569a" [[deps.AbstractFFTs]] deps = ["LinearAlgebra"] @@ -89,6 +89,28 @@ weakdeps = ["SparseArrays"] [deps.ChainRulesCore.extensions] ChainRulesCoreSparseArraysExt = "SparseArrays" +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "eb7f0f8307f71fac7c606984ea5fb2817275d6e4" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.11.4" + +[[deps.ColorVectorSpace]] +deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"] +git-tree-sha1 = "a1f44953f2382ebb937d60dafbe2deea4bd23249" +uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" +version = "0.10.0" +weakdeps = ["SpecialFunctions"] + + [deps.ColorVectorSpace.extensions] + SpecialFunctionsExt = "SpecialFunctions" + +[[deps.Colors]] +deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] +git-tree-sha1 = "fc08e5930ee9a4e03f84bfb5211cb54e7769758a" +uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" +version = "0.12.10" + [[deps.CommonSubexpressions]] deps = ["MacroTools", "Test"] git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7" @@ -108,7 +130,7 @@ weakdeps = ["Dates", "LinearAlgebra"] [[deps.CompilerSupportLibraries_jll]] deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.0.5+0" +version = "1.1.0+0" [[deps.ConstructionBase]] deps = ["LinearAlgebra"] @@ -124,6 +146,12 @@ version = "1.5.4" IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +[[deps.CoordinateTransformations]] +deps = ["LinearAlgebra", "StaticArrays"] +git-tree-sha1 = "f9d7112bfff8a19a3a4ea4e03a8e6a91fe8456bf" +uuid = "150eb455-5306-5404-9cee-2592286d6298" +version = "0.6.3" + [[deps.DataAPI]] git-tree-sha1 = "8da84edb865b0b5b0100c0666a9bc9a0b71c553c" uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" @@ -213,6 +241,12 @@ version = "2.22.0" BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +[[deps.FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.4" + [[deps.ForwardDiff]] deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"] git-tree-sha1 = "cf0fe81336da9fb90944683b8c41984b08793dad" @@ -233,6 +267,24 @@ version = "0.4.5" deps = ["Random"] uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" +[[deps.ImageBase]] +deps = ["ImageCore", "Reexport"] +git-tree-sha1 = "eb49b82c172811fd2c86759fa0553a2221feb909" +uuid = "c817782e-172a-44cc-b673-b171935fbb9e" +version = "0.1.7" + +[[deps.ImageCore]] +deps = ["ColorVectorSpace", "Colors", "FixedPointNumbers", "MappedArrays", "MosaicViews", "OffsetArrays", "PaddedViews", "PrecompileTools", "Reexport"] +git-tree-sha1 = "b2a7eaa169c13f5bcae8131a83bc30eff8f71be0" +uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534" +version = "0.10.2" + +[[deps.ImageTransformations]] +deps = ["AxisAlgorithms", "CoordinateTransformations", "ImageBase", "ImageCore", "Interpolations", "OffsetArrays", "Rotations", "StaticArrays"] +git-tree-sha1 = "e0884bdf01bbbb111aea77c348368a86fb4b5ab6" +uuid = "02fcd773-0e25-5acc-982a-7f6622650795" +version = "0.10.1" + [[deps.IntelOpenMP_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] git-tree-sha1 = "5fdf2fe6724d8caabf43b557b84ce53f3b7e2f6b" @@ -289,21 +341,26 @@ uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" [[deps.LibCURL]] deps = ["LibCURL_jll", "MozillaCACerts_jll"] uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" -version = "0.6.3" +version = "0.6.4" [[deps.LibCURL_jll]] deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" -version = "7.84.0+0" +version = "8.4.0+0" [[deps.LibGit2]] -deps = ["Base64", "NetworkOptions", "Printf", "SHA"] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.6.4+0" + [[deps.LibSSH2_jll]] deps = ["Artifacts", "Libdl", "MbedTLS_jll"] uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" -version = "1.10.2+0" +version = "1.11.0+1" [[deps.Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" @@ -349,6 +406,11 @@ git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df" uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" version = "0.5.13" +[[deps.MappedArrays]] +git-tree-sha1 = "2dab0221fe2b0f2cb6754eaa743cc266339f527e" +uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900" +version = "0.4.2" + [[deps.Markdown]] deps = ["Base64"] uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" @@ -362,7 +424,7 @@ version = "2.1.0" [[deps.MbedTLS_jll]] deps = ["Artifacts", "Libdl"] uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.28.2+0" +version = "2.28.2+1" [[deps.Missings]] deps = ["DataAPI"] @@ -373,9 +435,15 @@ version = "1.1.0" [[deps.Mmap]] uuid = "a63ad114-7e13-5084-954f-fe012c677804" +[[deps.MosaicViews]] +deps = ["MappedArrays", "OffsetArrays", "PaddedViews", "StackViews"] +git-tree-sha1 = "7b86a5d4d70a9f5cdf2dacb3cbe6d251d1a61dbe" +uuid = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389" +version = "0.3.4" + [[deps.MozillaCACerts_jll]] uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2022.10.11" +version = "2023.1.10" [[deps.NLSolversBase]] deps = ["DiffResults", "Distributed", "FiniteDiff", "ForwardDiff"] @@ -405,12 +473,12 @@ weakdeps = ["Adapt"] [[deps.OpenBLAS_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.21+4" +version = "0.3.23+4" [[deps.OpenLibm_jll]] deps = ["Artifacts", "Libdl"] uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.1+0" +version = "0.8.1+2" [[deps.OpenSpecFun_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] @@ -429,6 +497,12 @@ git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" version = "1.6.3" +[[deps.PaddedViews]] +deps = ["OffsetArrays"] +git-tree-sha1 = "0fac6313486baae819364c52b4f483450a9d793f" +uuid = "5432bcbf-9aad-5242-b902-cca2824c8663" +version = "0.5.12" + [[deps.Parameters]] deps = ["OrderedCollections", "UnPack"] git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe" @@ -438,7 +512,7 @@ version = "0.12.3" [[deps.Pkg]] deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.9.2" +version = "1.10.0" [[deps.Porcupine]] deps = ["ArrayPadding", "LinearAlgebra", "UnPack"] @@ -468,12 +542,18 @@ version = "1.4.1" deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +[[deps.Quaternions]] +deps = ["LinearAlgebra", "Random", "RealDot"] +git-tree-sha1 = "994cc27cdacca10e68feb291673ec3a76aa2fae9" +uuid = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0" +version = "0.7.6" + [[deps.REPL]] deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [[deps.Random]] -deps = ["SHA", "Serialization"] +deps = ["SHA"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" [[deps.Ratios]] @@ -481,12 +561,16 @@ deps = ["Requires"] git-tree-sha1 = "1342a47bf3260ee108163042310d26f2be5ec90b" uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439" version = "0.4.5" +weakdeps = ["FixedPointNumbers"] [deps.Ratios.extensions] RatiosFixedPointNumbersExt = "FixedPointNumbers" - [deps.Ratios.weakdeps] - FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +[[deps.RealDot]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9" +uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9" +version = "0.1.0" [[deps.Reexport]] git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" @@ -499,6 +583,18 @@ git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" uuid = "ae029012-a4dd-5104-9daa-d747884805df" version = "1.3.0" +[[deps.Rotations]] +deps = ["LinearAlgebra", "Quaternions", "Random", "StaticArrays"] +git-tree-sha1 = "2a0a5d8569f481ff8840e3b7c84bbf188db6a3fe" +uuid = "6038ab10-8711-5258-84ad-4b1120ba62dc" +version = "1.7.0" + + [deps.Rotations.extensions] + RotationsRecipesBaseExt = "RecipesBase" + + [deps.Rotations.weakdeps] + RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" + [[deps.SHA]] uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" version = "0.7.0" @@ -528,6 +624,7 @@ version = "1.2.1" [[deps.SparseArrays]] deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +version = "1.10.0" [[deps.SpecialFunctions]] deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] @@ -539,6 +636,12 @@ weakdeps = ["ChainRulesCore"] [deps.SpecialFunctions.extensions] SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" +[[deps.StackViews]] +deps = ["OffsetArrays"] +git-tree-sha1 = "46e589465204cd0c08b4bd97385e4fa79a0c770c" +uuid = "cae243ae-269e-4f55-b966-ac2d0dc13c15" +version = "0.1.1" + [[deps.StaticArrays]] deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] git-tree-sha1 = "f68dd04d131d9a8a8eb836173ee8f105c360b0c5" @@ -558,7 +661,7 @@ version = "1.4.2" [[deps.Statistics]] deps = ["LinearAlgebra", "SparseArrays"] uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -version = "1.9.0" +version = "1.10.0" [[deps.StatsAPI]] deps = ["LinearAlgebra"] @@ -577,9 +680,9 @@ deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" [[deps.SuiteSparse_jll]] -deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"] +deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "5.10.1+6" +version = "7.2.1+1" [[deps.TOML]] deps = ["Dates"] @@ -591,6 +694,12 @@ deps = ["ArgTools", "SHA"] uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" version = "1.10.0" +[[deps.TensorCore]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6" +uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50" +version = "0.1.1" + [[deps.Test]] deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" @@ -616,19 +725,19 @@ version = "1.0.0" [[deps.Zlib_jll]] deps = ["Libdl"] uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.13+0" +version = "1.2.13+1" [[deps.libblastrampoline_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.8.0+0" +version = "5.8.0+1" [[deps.nghttp2_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.48.0+0" +version = "1.52.0+1" [[deps.p7zip_jll]] deps = ["Artifacts", "Libdl"] uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.4.0+0" +version = "17.4.0+2" diff --git a/Project.toml b/Project.toml index 967914a..8b89a91 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ version = "0.1.0" ArrayPadding = "fe5ef43c-4912-423d-9170-4bd5cb6a013a" DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196" +ImageTransformations = "02fcd773-0e25-5acc-982a-7f6622650795" Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" Jello = "6872b481-e419-48a0-81d2-be4ee5684529" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/docs/.documenter-siteinfo.json b/docs/.documenter-siteinfo.json index 08cbe0a..9e53933 100644 --- a/docs/.documenter-siteinfo.json +++ b/docs/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.1","generation_timestamp":"2024-02-29T09:34:17","documenter_version":"1.2.1"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.1","generation_timestamp":"2024-02-29T10:11:56","documenter_version":"1.2.1"}} \ No newline at end of file diff --git a/docs/assets/3d_quarter_wavelength_antenna_nres_16.mp4 b/docs/assets/3d_quarter_wavelength_antenna_nres_16.mp4 index 61624c5..a69f9f1 100644 Binary files a/docs/assets/3d_quarter_wavelength_antenna_nres_16.mp4 and b/docs/assets/3d_quarter_wavelength_antenna_nres_16.mp4 differ diff --git a/docs/assets/3d_scattering_nres_16.mp4 b/docs/assets/3d_scattering_nres_16.mp4 index ff88763..344f2c7 100644 Binary files a/docs/assets/3d_scattering_nres_16.mp4 and b/docs/assets/3d_scattering_nres_16.mp4 differ diff --git a/docs/assets/guide copy/index.html b/docs/assets/guide copy/index.html new file mode 100644 index 0000000..fb2bab6 --- /dev/null +++ b/docs/assets/guide copy/index.html @@ -0,0 +1,2 @@ + +- · FDTDEngine.jl

Engineers run simulations to improve designs. Each time the design changes, the simulation is re-run. This can be done systematically in "parameter sweeps" where different combinations of parameter values are simulated to determine the best design. However, this scales exponentially wrt the number of parameters or DOFs.

General workflow

We use gradient descent, the same as in machine learning. In lieu of optimizing neural network parameters, we're optimizing geometry (or source) parameters. In each training iteration, we generate geometry, run the simulation, calculate the objective metric, and do a backward pass to derive the gradient wrt the geometry parameters. We then do a gradient based parameter update in preparation for the next iteration.

The geometry is thus the first step3. It typically has a static component which we can't change such as interfacing waveguides. Then there's a design component which we can change or optimize. The user is responsible for generating the design geometry wrt design parameters. If any pattern is allowed in the design region, our sister package Jello.jl can be used as a length scale controlled geometry generator. In any case, the result needs to be a 2d/3d array of each relevant materials property eg permitivity.

With geometry ready, we can run the simulation. Duration is roughly the time it takes to reach steady state, such as how long it take for the signal to reach output port. The objective is usually a steady state metric which can be computed using values from the final period. We optimize geometry for some objective.

diff --git a/docs/assets/index copy 2/index.html b/docs/assets/index copy 2/index.html new file mode 100644 index 0000000..d8365ec --- /dev/null +++ b/docs/assets/index copy 2/index.html @@ -0,0 +1,2 @@ + +- · FDTDEngine.jl
diff --git a/docs/assets/slab_waveguide.mp4 b/docs/assets/slab_waveguide.mp4 index 007e8b2..c982028 100644 Binary files a/docs/assets/slab_waveguide.mp4 and b/docs/assets/slab_waveguide.mp4 differ diff --git a/docs/guide/index.html b/docs/guide/index.html index 807bc4d..38085c1 100644 --- a/docs/guide/index.html +++ b/docs/guide/index.html @@ -1,2 +1,5 @@ -- · FDTDEngine.jl

Engineers run simulations to improve designs. Each time the design changes, the simulation is re-run. This can be done systematically in "parameter sweeps" where different combinations of parameter values are simulated to determine the best design. However, this scales exponentially wrt the number of parameters or DOFs.

General workflow

We use gradient descent, the same as in machine learning. In lieu of optimizing neural network parameters, we're optimizing geometry (or source) parameters. In each training iteration, we generate geometry, run the simulation, calculate the objective metric, and do a backward pass to derive the gradient wrt the geometry parameters. We then do a gradient based parameter update in preparation for the next iteration.

The geometry is thus the first step3. It typically has a static component which we can't change such as interfacing waveguides. Then there's a design component which we can change or optimize. The user is responsible for generating the design geometry wrt design parameters. If any pattern is allowed in the design region, our sister package Jello.jl can be used as a length scale controlled geometry generator. In any case, the result needs to be a 2d/3d array of each relevant materials property eg permitivity.

With geometry ready, we can run the simulation. Duration is roughly the time it takes to reach steady state, such as how long it take for the signal to reach output port. The objective is usually a steady state metric which can be computed using values from the final period. We optimize geometry for some objective.

+Guide · FDTDEngine.jl

Guide

Implementation

Length and time are in units of wavelength and period. This normalization allows usage of relative permitivity and permeability in equations . Fields including electric, magnetic and current density are simply bundled as a vector of vectors of arrays . Boundary conditions pad the field arrays . PML paddings are multilayered, while All other boundaries add single layers. Paddings are stateful and permanent, increasing the size of field and geometry arrays. Finite differencing happens every update step3 and are coordinated to implictly implement a staggered Yee's grid .

Sources

If a source has fewer nonzero dimensions than the simulation domain, its signal will get normalized along its singleton dimensions. For example, all planar sources in 3d or line sources in 2d will get scaled up by a factor of 1/dx. This way, discretisation would not affect radiated power.

Main.FDTDEngine.PlaneWaveType
function PlaneWave(f, dims; fields...)

Constructs plane wave source

Args

  • f: time function
  • dims: eg -1 for wave coming from -x face
  • fields: which fields to excite & their scaling constants (typically a current source, eg Jz=1)
source
Main.FDTDEngine.SourceType
function Source(f, c, lb, ub, label=""; fields...)
+function Source(f, c, L, label=""; fields...)

Constructs custom source. Can be used to specify uniform or modal sources

Args

  • f: time function
  • c: origin or center of source
  • lb: lower bounds wrt to c
  • ub: upper bounds wrt to c
  • L: source dimensions in [wavelengths]
  • fields: which fields to excite & their scaling constants (typically a current source, eg Jz=1)
source

Boundaries

Unspecified boundaries default to PML

Main.FDTDEngine.PMLType
function PML(dims, d=0.25f0, σ=20.0f0)

Constructs perfectly matched layers (PML aka ABC, RBC) boundary of depth d wavelengths Doesn't need to be explictly declared as all unspecified boundaries default to PML

source

Monitors

Main.FDTDEngine.MonitorType
function Monitor(c, L; normal=nothing, label="")
+function Monitor(c, lb, ub; normal=nothing, label="")

Constructs monitor which can span a point, line, surface, or volume monitoring fields or power.

Args

  • c: origin or center of monitor

  • L: physical dimensions of monitor

  • lb: lower bounds wrt to c

  • ub: upper bounds wrt to c

  • normal: flux monitor direction (eg normal to flux surface)

source

Physics

Main.FDTDEngine.step3!Function
function step3!(u, p, t, field_padding, source_instances)
+function step3!(u1, u, p, t, field_padding, source_instances)

Updates fields for 3d. Please use step3 instead of step3! when doing AD. Mutating step3! Writes new fields either onto old fields or into buffer arrays u1

source
Main.FDTDEngine.step3Function
function step3(u, p, t, field_padding, source_instances)

Updates fields for 3d in a manner amenable to AD. See also Mutating step3!

source

GPU support

Simply use Flux.gpu to move simulation variables to GPU. This turns Arrays into CUDA arrays which get processed on GPU for both forward and backpropagation passes

Automatic differentiation adjoints

Compatible with Zygote.jl and Flux.jl. Please use step3 instead of step3! when doing AD. See inverse design examples

Generative inverse design

Please contact us for latest scripts. We wrote Jello.jl, an innovative Fourier domain neural model to generate length scale controlled efficiently paramaterized geometry .

Comparison with other FDTD software

Our focus is on inverse design and topology optimization using adjoints from automatic differentiation. We love a streamlined API backed by a clear, concise and extensible codebase. Attention is paid to speed and malloc but that's not our main concern. Meep is the most popular open source FDTD package owing to its maturity and comprehensive features. It supports AD in certain cases using custom adjoints which we avoid in our package in favor of more flexibility . There are numerous commercial software eg Ansys Lumerical, Comsol and various EDA or SI software. TMK none of them supports AD for inverse design

diff --git a/docs/index.html b/docs/index.html index 4e0640e..55569ed 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,41 +1,38 @@ -Home · FDTDEngine.jl

Home

Currently Prerelease. Expect breaking changes. Report bugs on (Github )[ https://github.com/paulxshen/FDTDEngine.jl] - we usually respond within a day

Overview

Generative design meets Maxwell's Equations. Differentiable FDTD package for inverse design & topology optimization in semiconductor photonics, acoustics and RF. GPU and automatic differentiation (AD) compatible. Uses AD by Zygote.jl for adjoint optimization. Integrates with Jello.jl to generate length scale controlled paramaterized geometry . Staggered Yee grid update with fully featured boundary conditions & sources. Customizable physics to potentially incorporate dynamics like heat transfer, charge transport.

Quarter wavelength antenna radiating above conductive ground plane

Simulation of coupling into dielectric slab waveguide using modal source

Simulation of plane wave scattering on Periodic array

Generative Inverse design of compact silicon photonics splitter

Installation

Install via

Pkg.add(url="https://github.com/paulxshen/FDTDEngine.jl")
+Home · FDTDEngine.jl

Home

Currently Prerelease. Expect breaking changes. Report bugs on Github - we usually respond within a day

Overview

Generative design meets Maxwell's Equations. Differentiable FDTD package for inverse design & topology optimization in semiconductor photonics, acoustics and RF. GPU and automatic differentiation (AD) compatible. Uses AD by Zygote.jl for adjoint optimization. Integrates with Jello.jl to generate length scale controlled paramaterized geometry . Staggered Yee grid update with fully featured boundary conditions & sources. Customizable physics to potentially incorporate dynamics like heat transfer, charge transport.

Quarter wavelength antenna radiating above conductive ground plane

Simulation of coupling into dielectric slab waveguide using modal source

Simulation of plane wave scattering on Periodic array

Generative Inverse design of compact silicon photonics splitter

Installation

Install via

Pkg.add(url="https://github.com/paulxshen/FDTDEngine.jl")
 Pkg.add(url="https://github.com/paulxshen/FDTDToolkit.jl")

FDTDToolkit.jl contains visualization utilities

Quickstart

We do a quick 3d simulation of plane wave scattering on periodic array of dielectric spheres (see gallery movie)

"""
 simulation of plane wave scattering on periodic array of dielectric spheres
 """
 
 using UnPack, LinearAlgebra, GLMakie
-# using FDTDEngine,FDTDToolkit
-dir = pwd()
-include("$(dir)/src/main.jl")
-include("$dir/../FDTDToolkit.jl/src/main.jl")
+using FDTDEngine,FDTDToolkit
+dogpu = true
+# dogpu = false
 
+name = "periodic_scattering"
+T = 10 # simulation duration in [periods]
+nx = 20
+dx = 1.0 / nx # pixel resolution in [wavelengths]
 
-name = "3d_scattering"
-T = 8.0f0 # simulation duration in [periods]
-nx = 16
-dx = 1.0f0 / nx # pixel resolution in [wavelengths]
-
-"geometry"
-l = 2 # domain physical size length
+# geometry
+l = 2 # domain physical size length in [wavelengths]
 sz = nx .* (l, l, l) # domain voxel dimensions
 ϵ1 = ϵmin = 1 #
-ϵ2 = 2.25f0 # 
+ϵ2 = 2.25 # 
 b = F.([norm(v .- sz ./ 2) < 0.5 / dx for v = Base.product(Base.oneto.(sz)...)]) # sphere
 ϵ = ϵ2 * b + ϵ1 * (1 .- b)
 
-"setup"
+# setup
 boundaries = [Periodic(2), Periodic(3)]# unspecified boundaries default to PML
 sources = [
-    PlaneWave(t -> cos(F(2π) * t), -1; Jz=1) # Jz excited plane wave from -x plane (eg -1)
+    PlaneWave(t -> cos(2π * t), -1; Jz=1) # Jz excited plane wave from -x plane (eg -1)
 ]
-n = [1, 0, 0] # normal 
-δ = 0.2f0 # margin
-# A = (l - δ)^2
+normal = [1, 0, 0] #  
+δ = 0.2 # margin
 lm = 1 # monitor side length
 monitors = [
-    Monitor([δ, l / 2, l / 2], [0, lm, lm], n,), # (center, dimensions, normal)
-    Monitor([l - δ, l / 2, l / 2], [0, lm, lm], n,),
+    Monitor([δ, l / 2, l / 2], [0, lm, lm]; normal), # (center, dimensions; normal)
+    Monitor([l - δ, l / 2, l / 2], [0, lm, lm]; normal),
 ]
 configs = setup(boundaries, sources, monitors, dx, sz; ϵmin, T)
 @unpack μ, σ, σm, dt, geometry_padding, geometry_splits, field_padding, source_instances, monitor_instances, u0, = configs
@@ -43,35 +40,38 @@
 ϵ, μ, σ, σm = apply(geometry_padding; ϵ, μ, σ, σm)
 p = apply(geometry_splits; ϵ, μ, σ, σm)
 
+# move to gpu
+if dogpu
+    using CUDA, Flux
+    @assert CUDA.functional()
+    u0, p, field_padding, source_instances = gpu.((u0, p, field_padding, source_instances))
+end
 
 # run simulation
-t = 0:dt:T
-u = [[similar.(a) for a = u0] for t = t]
-u[1] = u0
-@showtime reduce(
-    (u, (u1, t)) -> step3!(u1, u, p, t, dx, dt, field_padding, source_instances),
-    zip(u[2:end], t[1:end-1]),
-    init=u0)
-y = hcat([power.((m,), u) for m = monitor_instances]...)
+@showtime u = accumulate(0:dt:T, init=u0) do u, t
+    step3!(deepcopy(u), p, t, dx, dt, field_padding, source_instances)
+end
+y = [power.((m,), u) for m = monitor_instances]
 
-# make movie
+# move back to cpu for plotting
+if dogpu
+    u, p, field_padding, source_instances = cpu.((u, p, field_padding, source_instances))
+end
+
+# make movie, 
 Ez = map(u) do u
     u[1][3]
 end
-ϵz = p[1][3]
+ϵEz = p[1][3]
 dir = @__DIR__
-
-recordsim("$dir/$(name)_nres_$nx.mp4", Ez, y;
+recordsim("$dir/$(name).mp4", Ez, y;
     dt,
+    field=:Ez,
     monitor_instances,
     source_instances,
-    geometry=ϵz,
+    geometry=ϵEz,
     elevation=30°,
     playback=1,
     axis1=(; title="$name\nEz"),
     axis2=(; title="monitor powers"),
-)
-

Guide

Implementation

<!– Supports 1d (Ez, Hy), 2d TMz (Ez, Hx, Hy), 2d TEz (Hz, Ex, Ey) and 3d. –> Length and time are in units of wavelength and period. This normalization allows usage of relative permitivity and permeability in equations . Fields including electric, magnetic and current density are simply bundled as a vector of vectors of arrays . Boundary conditions pad the field arrays . PML paddings are multilayered, while All other boundaries add single layers. Paddings are stateful and permanent, increasing the size of field and geometry arrays. Finite differencing happens every update step3 and are coordinated to implictly implement a staggered Yee's grid .

Sources

If a source has fewer nonzero dimensions than the simulation domain, its signal will get normalized along its singleton dimensions. For example, all planar sources in 3d or line sources in 2d will get scaled up by a factor of 1/dx. This way, discretisation would not affect radiated power.

Main.FDTDEngine.PlaneWaveType
function PlaneWave(f, dims; fields...)

Constructs plane wave source

Args

  • f: time function
  • dims: eg -1 for wave coming from -x face
  • fields: which fields to excite & their scaling constants (typically a current source, eg Jz=1)
source
Main.FDTDEngine.SourceType
function Source(f, c, lb, ub, label=""; fields...)
-function Source(f, c, L, label=""; fields...)

Constructs custom source. Can be used to specify uniform or modal sources

Args

  • f: time function
  • c: origin or center of source
  • lb: lower bounds wrt to c
  • ub: upper bounds wrt to c
  • L: source dimensions in [wavelengths]
  • fields: which fields to excite & their scaling constants (typically a current source, eg Jz=1)
source

<!– GaussianBeam –>

Boundaries

Unspecified boundaries default to PML

Main.FDTDEngine.PMLType
function PML(dims, d=0.25f0, σ=20.0f0)

Constructs perfectly matched layers (PML aka ABC, RBC) boundary of depth d wavelengths Doesn't need to be explictly declared as all unspecified boundaries default to PML

source

Monitors

Main.FDTDEngine.MonitorType
function Monitor(c, L; normal=nothing, label="")
-function Monitor(c, lb, ub; normal=nothing, label="")

Constructs monitor which can span a point, line, surface, or volume monitoring fields or power.

Args

  • c: origin or center of monitor

  • L: physical dimensions of monitor

  • lb: lower bounds wrt to c

  • ub: upper bounds wrt to c

  • normal: flux monitor direction (eg normal to flux surface)

source

Physics

Main.FDTDEngine.step3!Function
function step3!(u, p, t, field_padding, source_instances)
-function step3!(u1, u, p, t, field_padding, source_instances)

Updates fields for 3d. Please use step3 instead of step3! when doing AD. Mutating step3! Writes new fields either onto old fields or into buffer arrays u1

source
Main.FDTDEngine.step3Function
function step3(u, p, t, field_padding, source_instances)

Updates fields for 3d in a manner amenable to AD. See also Mutating step3!

source

<!– step1 –> <!– stepTMz –> <!– stepTEz –>

GPU support

Simply use Flux.gpu to move simulation variables to GPU. This turns Arrays into CUDA arrays which get processed on GPU for both forward and backpropagation passes

Automatic differentiation adjoints

Compatible with Zygote.jl and Flux.jl. Please use step3 instead of step3! when doing AD. See inverse design examples

Generative inverse design

Please contact us for latest scripts. We wrote (Jello.jl)[https://github.com/paulxshen/Jello.jl], an innovative Fourier domain neural model to generate length scale controlled efficiently paramaterized geometry .

Comparison with other FDTD software

Our focus is on inverse design and topology optimization using adjoints from automatic differentiation. We love a streamlined API backed by a clear, concise and extensible codebase. Attention is paid to speed and malloc but that's not our main concern. Meep is the most popular open source FDTD package owing to its maturity and comprehensive features. It supports AD in certain cases using custom adjoints which we avoid in our package in favor of more flexibility . There are numerous commercial software eg Ansys Lumerical, Comsol and various EDA or SI software. TMK none of them supports AD for inverse design

Tutorials

see (examples/)[https://github.com/paulxshen/FDTDEngine.jl/blob/main/examples/]

People

Community

Discussion & updates at Julia Discourse

Contributors

Paul Shen <pxshen@alumni.stanford.edu> Consulting and technical support available 2024 (c) Paul Shen

+)
diff --git a/docs/people/index.html b/docs/people/index.html new file mode 100644 index 0000000..0e8ad2a --- /dev/null +++ b/docs/people/index.html @@ -0,0 +1,2 @@ + +People · FDTDEngine.jl
diff --git a/docs/search_index.js b/docs/search_index.js index b81c9f7..1d8a6c3 100644 --- a/docs/search_index.js +++ b/docs/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"guide/#","page":"-","title":"","text":"","category":"section"},{"location":"guide/","page":"-","title":"-","text":"Engineers run simulations to improve designs. Each time the design changes, the simulation is re-run. This can be done systematically in \"parameter sweeps\" where different combinations of parameter values are simulated to determine the best design. However, this scales exponentially wrt the number of parameters or DOFs. ","category":"page"},{"location":"guide/#General-workflow","page":"-","title":"General workflow","text":"","category":"section"},{"location":"guide/","page":"-","title":"-","text":"We use gradient descent, the same as in machine learning. In lieu of optimizing neural network parameters, we're optimizing geometry (or source) parameters. In each training iteration, we generate geometry, run the simulation, calculate the objective metric, and do a backward pass to derive the gradient wrt the geometry parameters. We then do a gradient based parameter update in preparation for the next iteration.","category":"page"},{"location":"guide/","page":"-","title":"-","text":"The geometry is thus the first step3. It typically has a static component which we can't change such as interfacing waveguides. Then there's a design component which we can change or optimize. The user is responsible for generating the design geometry wrt design parameters. If any pattern is allowed in the design region, our sister package Jello.jl can be used as a length scale controlled geometry generator. In any case, the result needs to be a 2d/3d array of each relevant materials property eg permitivity. ","category":"page"},{"location":"guide/","page":"-","title":"-","text":"With geometry ready, we can run the simulation. Duration is roughly the time it takes to reach steady state, such as how long it take for the signal to reach output port. The objective is usually a steady state metric which can be computed using values from the final period. We optimize geometry for some objective. ","category":"page"},{"location":"#Home","page":"Home","title":"Home","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Currently Prerelease. Expect breaking changes. Report bugs on (Github )[ https://github.com/paulxshen/FDTDEngine.jl] - we usually respond within a day","category":"page"},{"location":"#Overview","page":"Home","title":"Overview","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Generative design meets Maxwell's Equations. Differentiable FDTD package for inverse design & topology optimization in semiconductor photonics, acoustics and RF. GPU and automatic differentiation (AD) compatible. Uses AD by Zygote.jl for adjoint optimization. Integrates with Jello.jl to generate length scale controlled paramaterized geometry . Staggered Yee grid update with fully featured boundary conditions & sources. Customizable physics to potentially incorporate dynamics like heat transfer, charge transport.","category":"page"},{"location":"#Gallery","page":"Home","title":"Gallery","text":"","category":"section"},{"location":"#Quarter-wavelength-antenna-radiating-above-conductive-ground-plane","page":"Home","title":"Quarter wavelength antenna radiating above conductive ground plane","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: )","category":"page"},{"location":"#Simulation-of-coupling-into-dielectric-slab-waveguide-using-modal-source","page":"Home","title":"Simulation of coupling into dielectric slab waveguide using modal source","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: )","category":"page"},{"location":"#Simulation-of-plane-wave-scattering-on-Periodic-array","page":"Home","title":"Simulation of plane wave scattering on Periodic array","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: )","category":"page"},{"location":"#Generative-Inverse-design-of-compact-silicon-photonics-splitter","page":"Home","title":"Generative Inverse design of compact silicon photonics splitter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: )","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Install via ","category":"page"},{"location":"","page":"Home","title":"Home","text":"Pkg.add(url=\"https://github.com/paulxshen/FDTDEngine.jl\")\nPkg.add(url=\"https://github.com/paulxshen/FDTDToolkit.jl\")","category":"page"},{"location":"","page":"Home","title":"Home","text":"FDTDToolkit.jl contains visualization utilities","category":"page"},{"location":"#Quickstart","page":"Home","title":"Quickstart","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"We do a quick 3d simulation of plane wave scattering on periodic array of dielectric spheres (see gallery movie)","category":"page"},{"location":"","page":"Home","title":"Home","text":"\"\"\"\nsimulation of plane wave scattering on periodic array of dielectric spheres\n\"\"\"\n\nusing UnPack, LinearAlgebra, GLMakie\n# using FDTDEngine,FDTDToolkit\ndir = pwd()\ninclude(\"$(dir)/src/main.jl\")\ninclude(\"$dir/../FDTDToolkit.jl/src/main.jl\")\n\n\nname = \"3d_scattering\"\nT = 8.0f0 # simulation duration in [periods]\nnx = 16\ndx = 1.0f0 / nx # pixel resolution in [wavelengths]\n\n\"geometry\"\nl = 2 # domain physical size length\nsz = nx .* (l, l, l) # domain voxel dimensions\nϵ1 = ϵmin = 1 #\nϵ2 = 2.25f0 # \nb = F.([norm(v .- sz ./ 2) < 0.5 / dx for v = Base.product(Base.oneto.(sz)...)]) # sphere\nϵ = ϵ2 * b + ϵ1 * (1 .- b)\n\n\"setup\"\nboundaries = [Periodic(2), Periodic(3)]# unspecified boundaries default to PML\nsources = [\n PlaneWave(t -> cos(F(2π) * t), -1; Jz=1) # Jz excited plane wave from -x plane (eg -1)\n]\nn = [1, 0, 0] # normal \nδ = 0.2f0 # margin\n# A = (l - δ)^2\nlm = 1 # monitor side length\nmonitors = [\n Monitor([δ, l / 2, l / 2], [0, lm, lm], n,), # (center, dimensions, normal)\n Monitor([l - δ, l / 2, l / 2], [0, lm, lm], n,),\n]\nconfigs = setup(boundaries, sources, monitors, dx, sz; ϵmin, T)\n@unpack μ, σ, σm, dt, geometry_padding, geometry_splits, field_padding, source_instances, monitor_instances, u0, = configs\n\nϵ, μ, σ, σm = apply(geometry_padding; ϵ, μ, σ, σm)\np = apply(geometry_splits; ϵ, μ, σ, σm)\n\n\n# run simulation\nt = 0:dt:T\nu = [[similar.(a) for a = u0] for t = t]\nu[1] = u0\n@showtime reduce(\n (u, (u1, t)) -> step3!(u1, u, p, t, dx, dt, field_padding, source_instances),\n zip(u[2:end], t[1:end-1]),\n init=u0)\ny = hcat([power.((m,), u) for m = monitor_instances]...)\n\n# make movie\nEz = map(u) do u\n u[1][3]\nend\nϵz = p[1][3]\ndir = @__DIR__\n\nrecordsim(\"$dir/$(name)_nres_$nx.mp4\", Ez, y;\n dt,\n monitor_instances,\n source_instances,\n geometry=ϵz,\n elevation=30°,\n playback=1,\n axis1=(; title=\"$name\\nEz\"),\n axis2=(; title=\"monitor powers\"),\n)\n","category":"page"},{"location":"#Guide","page":"Home","title":"Guide","text":"","category":"section"},{"location":"#Implementation","page":"Home","title":"Implementation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":" Length and time are in units of wavelength and period. This normalization allows usage of relative permitivity and permeability in equations . Fields including electric, magnetic and current density are simply bundled as a vector of vectors of arrays . Boundary conditions pad the field arrays . PML paddings are multilayered, while All other boundaries add single layers. Paddings are stateful and permanent, increasing the size of field and geometry arrays. Finite differencing happens every update step3 and are coordinated to implictly implement a staggered Yee's grid .","category":"page"},{"location":"#Sources","page":"Home","title":"Sources","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"If a source has fewer nonzero dimensions than the simulation domain, its signal will get normalized along its singleton dimensions. For example, all planar sources in 3d or line sources in 2d will get scaled up by a factor of 1/dx. This way, discretisation would not affect radiated power.","category":"page"},{"location":"","page":"Home","title":"Home","text":"PlaneWave\nSource","category":"page"},{"location":"#Main.FDTDEngine.PlaneWave","page":"Home","title":"Main.FDTDEngine.PlaneWave","text":"function PlaneWave(f, dims; fields...)\n\nConstructs plane wave source\n\nArgs\n\nf: time function\ndims: eg -1 for wave coming from -x face\nfields: which fields to excite & their scaling constants (typically a current source, eg Jz=1)\n\n\n\n\n\n","category":"type"},{"location":"#Main.FDTDEngine.Source","page":"Home","title":"Main.FDTDEngine.Source","text":"function Source(f, c, lb, ub, label=\"\"; fields...)\nfunction Source(f, c, L, label=\"\"; fields...)\n\nConstructs custom source. Can be used to specify uniform or modal sources\n\nArgs\n\nf: time function\nc: origin or center of source\nlb: lower bounds wrt to c\nub: upper bounds wrt to c\nL: source dimensions in [wavelengths]\nfields: which fields to excite & their scaling constants (typically a current source, eg Jz=1)\n\n\n\n\n\n","category":"type"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"#Boundaries","page":"Home","title":"Boundaries","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Unspecified boundaries default to PML ","category":"page"},{"location":"","page":"Home","title":"Home","text":"Periodic\nPML\nPEC\nPMC","category":"page"},{"location":"#Main.FDTDEngine.Periodic","page":"Home","title":"Main.FDTDEngine.Periodic","text":"Periodic(dims)\n\nperiodic boundary\n\n\n\n\n\n","category":"type"},{"location":"#Main.FDTDEngine.PML","page":"Home","title":"Main.FDTDEngine.PML","text":"function PML(dims, d=0.25f0, σ=20.0f0)\n\nConstructs perfectly matched layers (PML aka ABC, RBC) boundary of depth d wavelengths Doesn't need to be explictly declared as all unspecified boundaries default to PML\n\n\n\n\n\n","category":"type"},{"location":"#Main.FDTDEngine.PEC","page":"Home","title":"Main.FDTDEngine.PEC","text":"PEC(dims)\n\nperfect electrical conductor dims: eg -1 for -x side\n\n\n\n\n\n","category":"type"},{"location":"#Main.FDTDEngine.PMC","page":"Home","title":"Main.FDTDEngine.PMC","text":"PMC(dims)\n\nperfect magnetic conductor\n\n\n\n\n\n","category":"type"},{"location":"#Monitors","page":"Home","title":"Monitors","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Monitor\npower\npower_density","category":"page"},{"location":"#Main.FDTDEngine.Monitor","page":"Home","title":"Main.FDTDEngine.Monitor","text":"function Monitor(c, L; normal=nothing, label=\"\")\nfunction Monitor(c, lb, ub; normal=nothing, label=\"\")\n\nConstructs monitor which can span a point, line, surface, or volume monitoring fields or power. \n\nArgs\n\nc: origin or center of monitor\nL: physical dimensions of monitor\nlb: lower bounds wrt to c\nub: upper bounds wrt to c\nnormal: flux monitor direction (eg normal to flux surface)\n\n\n\n\n\n","category":"type"},{"location":"#Main.FDTDEngine.power","page":"Home","title":"Main.FDTDEngine.power","text":"function power(m::MonitorInstance, u)\n\ntotal power (Poynting flux) passing thru monitor surface\n\n\n\n\n\n","category":"function"},{"location":"#Main.FDTDEngine.power_density","page":"Home","title":"Main.FDTDEngine.power_density","text":"function power_density(m::MonitorInstance, u)\n\npower density (avg Poynting flux) passing thru monitor surface\n\n\n\n\n\n","category":"function"},{"location":"#Physics","page":"Home","title":"Physics","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"step3!\nstep3","category":"page"},{"location":"#Main.FDTDEngine.step3!","page":"Home","title":"Main.FDTDEngine.step3!","text":"function step3!(u, p, t, field_padding, source_instances)\nfunction step3!(u1, u, p, t, field_padding, source_instances)\n\nUpdates fields for 3d. Please use step3 instead of step3! when doing AD. Mutating step3! Writes new fields either onto old fields or into buffer arrays u1\n\n\n\n\n\n","category":"function"},{"location":"#Main.FDTDEngine.step3","page":"Home","title":"Main.FDTDEngine.step3","text":"function step3(u, p, t, field_padding, source_instances)\n\nUpdates fields for 3d in a manner amenable to AD. See also Mutating step3!\n\n\n\n\n\n","category":"function"},{"location":"","page":"Home","title":"Home","text":" ","category":"page"},{"location":"#GPU-support","page":"Home","title":"GPU support","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Simply use Flux.gpu to move simulation variables to GPU. This turns Arrays into CUDA arrays which get processed on GPU for both forward and backpropagation passes","category":"page"},{"location":"#Automatic-differentiation-adjoints","page":"Home","title":"Automatic differentiation adjoints","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Compatible with Zygote.jl and Flux.jl. Please use step3 instead of step3! when doing AD. See inverse design examples ","category":"page"},{"location":"#Generative-inverse-design","page":"Home","title":"Generative inverse design","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Please contact us for latest scripts. We wrote (Jello.jl)[https://github.com/paulxshen/Jello.jl], an innovative Fourier domain neural model to generate length scale controlled efficiently paramaterized geometry .","category":"page"},{"location":"#Comparison-with-other-FDTD-software","page":"Home","title":"Comparison with other FDTD software","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Our focus is on inverse design and topology optimization using adjoints from automatic differentiation. We love a streamlined API backed by a clear, concise and extensible codebase. Attention is paid to speed and malloc but that's not our main concern. Meep is the most popular open source FDTD package owing to its maturity and comprehensive features. It supports AD in certain cases using custom adjoints which we avoid in our package in favor of more flexibility . There are numerous commercial software eg Ansys Lumerical, Comsol and various EDA or SI software. TMK none of them supports AD for inverse design ","category":"page"},{"location":"#Tutorials","page":"Home","title":"Tutorials","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"see (examples/)[https://github.com/paulxshen/FDTDEngine.jl/blob/main/examples/]","category":"page"},{"location":"#People","page":"Home","title":"People","text":"","category":"section"},{"location":"#Community","page":"Home","title":"Community","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Discussion & updates at Julia Discourse","category":"page"},{"location":"#Contributors","page":"Home","title":"Contributors","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Paul Shen Consulting and technical support available 2024 (c) Paul Shen","category":"page"}] +[{"location":"guide/#Guide","page":"Guide","title":"Guide","text":"","category":"section"},{"location":"guide/#Implementation","page":"Guide","title":"Implementation","text":"","category":"section"},{"location":"guide/","page":"Guide","title":"Guide","text":"Length and time are in units of wavelength and period. This normalization allows usage of relative permitivity and permeability in equations . Fields including electric, magnetic and current density are simply bundled as a vector of vectors of arrays . Boundary conditions pad the field arrays . PML paddings are multilayered, while All other boundaries add single layers. Paddings are stateful and permanent, increasing the size of field and geometry arrays. Finite differencing happens every update step3 and are coordinated to implictly implement a staggered Yee's grid .","category":"page"},{"location":"guide/#Sources","page":"Guide","title":"Sources","text":"","category":"section"},{"location":"guide/","page":"Guide","title":"Guide","text":"If a source has fewer nonzero dimensions than the simulation domain, its signal will get normalized along its singleton dimensions. For example, all planar sources in 3d or line sources in 2d will get scaled up by a factor of 1/dx. This way, discretisation would not affect radiated power.","category":"page"},{"location":"guide/","page":"Guide","title":"Guide","text":"PlaneWave\nSource","category":"page"},{"location":"guide/#Main.FDTDEngine.PlaneWave","page":"Guide","title":"Main.FDTDEngine.PlaneWave","text":"function PlaneWave(f, dims; fields...)\n\nConstructs plane wave source\n\nArgs\n\nf: time function\ndims: eg -1 for wave coming from -x face\nfields: which fields to excite & their scaling constants (typically a current source, eg Jz=1)\n\n\n\n\n\n","category":"type"},{"location":"guide/#Main.FDTDEngine.Source","page":"Guide","title":"Main.FDTDEngine.Source","text":"function Source(f, c, lb, ub, label=\"\"; fields...)\nfunction Source(f, c, L, label=\"\"; fields...)\n\nConstructs custom source. Can be used to specify uniform or modal sources\n\nArgs\n\nf: time function\nc: origin or center of source\nlb: lower bounds wrt to c\nub: upper bounds wrt to c\nL: source dimensions in [wavelengths]\nfields: which fields to excite & their scaling constants (typically a current source, eg Jz=1)\n\n\n\n\n\n","category":"type"},{"location":"guide/#Boundaries","page":"Guide","title":"Boundaries","text":"","category":"section"},{"location":"guide/","page":"Guide","title":"Guide","text":"Unspecified boundaries default to PML ","category":"page"},{"location":"guide/","page":"Guide","title":"Guide","text":"Periodic\nPML\nPEC\nPMC","category":"page"},{"location":"guide/#Main.FDTDEngine.Periodic","page":"Guide","title":"Main.FDTDEngine.Periodic","text":"Periodic(dims)\n\nperiodic boundary\n\n\n\n\n\n","category":"type"},{"location":"guide/#Main.FDTDEngine.PML","page":"Guide","title":"Main.FDTDEngine.PML","text":"function PML(dims, d=0.25f0, σ=20.0f0)\n\nConstructs perfectly matched layers (PML aka ABC, RBC) boundary of depth d wavelengths Doesn't need to be explictly declared as all unspecified boundaries default to PML\n\n\n\n\n\n","category":"type"},{"location":"guide/#Main.FDTDEngine.PEC","page":"Guide","title":"Main.FDTDEngine.PEC","text":"PEC(dims)\n\nperfect electrical conductor dims: eg -1 for -x side\n\n\n\n\n\n","category":"type"},{"location":"guide/#Main.FDTDEngine.PMC","page":"Guide","title":"Main.FDTDEngine.PMC","text":"PMC(dims)\n\nperfect magnetic conductor\n\n\n\n\n\n","category":"type"},{"location":"guide/#Monitors","page":"Guide","title":"Monitors","text":"","category":"section"},{"location":"guide/","page":"Guide","title":"Guide","text":"Monitor\npower\npower_density","category":"page"},{"location":"guide/#Main.FDTDEngine.Monitor","page":"Guide","title":"Main.FDTDEngine.Monitor","text":"function Monitor(c, L; normal=nothing, label=\"\")\nfunction Monitor(c, lb, ub; normal=nothing, label=\"\")\n\nConstructs monitor which can span a point, line, surface, or volume monitoring fields or power. \n\nArgs\n\nc: origin or center of monitor\nL: physical dimensions of monitor\nlb: lower bounds wrt to c\nub: upper bounds wrt to c\nnormal: flux monitor direction (eg normal to flux surface)\n\n\n\n\n\n","category":"type"},{"location":"guide/#Main.FDTDEngine.power","page":"Guide","title":"Main.FDTDEngine.power","text":"function power(m::MonitorInstance, u)\n\ntotal power (Poynting flux) passing thru monitor surface\n\n\n\n\n\n","category":"function"},{"location":"guide/#Main.FDTDEngine.power_density","page":"Guide","title":"Main.FDTDEngine.power_density","text":"function power_density(m::MonitorInstance, u)\n\npower density (avg Poynting flux) passing thru monitor surface\n\n\n\n\n\n","category":"function"},{"location":"guide/#Physics","page":"Guide","title":"Physics","text":"","category":"section"},{"location":"guide/","page":"Guide","title":"Guide","text":"step3!\nstep3","category":"page"},{"location":"guide/#Main.FDTDEngine.step3!","page":"Guide","title":"Main.FDTDEngine.step3!","text":"function step3!(u, p, t, field_padding, source_instances)\nfunction step3!(u1, u, p, t, field_padding, source_instances)\n\nUpdates fields for 3d. Please use step3 instead of step3! when doing AD. Mutating step3! Writes new fields either onto old fields or into buffer arrays u1\n\n\n\n\n\n","category":"function"},{"location":"guide/#Main.FDTDEngine.step3","page":"Guide","title":"Main.FDTDEngine.step3","text":"function step3(u, p, t, field_padding, source_instances)\n\nUpdates fields for 3d in a manner amenable to AD. See also Mutating step3!\n\n\n\n\n\n","category":"function"},{"location":"guide/#GPU-support","page":"Guide","title":"GPU support","text":"","category":"section"},{"location":"guide/","page":"Guide","title":"Guide","text":"Simply use Flux.gpu to move simulation variables to GPU. This turns Arrays into CUDA arrays which get processed on GPU for both forward and backpropagation passes","category":"page"},{"location":"guide/#Automatic-differentiation-adjoints","page":"Guide","title":"Automatic differentiation adjoints","text":"","category":"section"},{"location":"guide/","page":"Guide","title":"Guide","text":"Compatible with Zygote.jl and Flux.jl. Please use step3 instead of step3! when doing AD. See inverse design examples ","category":"page"},{"location":"guide/#Generative-inverse-design","page":"Guide","title":"Generative inverse design","text":"","category":"section"},{"location":"guide/","page":"Guide","title":"Guide","text":"Please contact us for latest scripts. We wrote Jello.jl, an innovative Fourier domain neural model to generate length scale controlled efficiently paramaterized geometry .","category":"page"},{"location":"guide/#Comparison-with-other-FDTD-software","page":"Guide","title":"Comparison with other FDTD software","text":"","category":"section"},{"location":"guide/","page":"Guide","title":"Guide","text":"Our focus is on inverse design and topology optimization using adjoints from automatic differentiation. We love a streamlined API backed by a clear, concise and extensible codebase. Attention is paid to speed and malloc but that's not our main concern. Meep is the most popular open source FDTD package owing to its maturity and comprehensive features. It supports AD in certain cases using custom adjoints which we avoid in our package in favor of more flexibility . There are numerous commercial software eg Ansys Lumerical, Comsol and various EDA or SI software. TMK none of them supports AD for inverse design ","category":"page"},{"location":"tutorials/#Tutorials","page":"Tutorials","title":"Tutorials","text":"","category":"section"},{"location":"tutorials/","page":"Tutorials","title":"Tutorials","text":"see examples/","category":"page"},{"location":"assets/guide copy/#","page":"-","title":"","text":"","category":"section"},{"location":"assets/guide copy/","page":"-","title":"-","text":"Engineers run simulations to improve designs. Each time the design changes, the simulation is re-run. This can be done systematically in \"parameter sweeps\" where different combinations of parameter values are simulated to determine the best design. However, this scales exponentially wrt the number of parameters or DOFs. ","category":"page"},{"location":"assets/guide copy/#General-workflow","page":"-","title":"General workflow","text":"","category":"section"},{"location":"assets/guide copy/","page":"-","title":"-","text":"We use gradient descent, the same as in machine learning. In lieu of optimizing neural network parameters, we're optimizing geometry (or source) parameters. In each training iteration, we generate geometry, run the simulation, calculate the objective metric, and do a backward pass to derive the gradient wrt the geometry parameters. We then do a gradient based parameter update in preparation for the next iteration.","category":"page"},{"location":"assets/guide copy/","page":"-","title":"-","text":"The geometry is thus the first step3. It typically has a static component which we can't change such as interfacing waveguides. Then there's a design component which we can change or optimize. The user is responsible for generating the design geometry wrt design parameters. If any pattern is allowed in the design region, our sister package Jello.jl can be used as a length scale controlled geometry generator. In any case, the result needs to be a 2d/3d array of each relevant materials property eg permitivity. ","category":"page"},{"location":"assets/guide copy/","page":"-","title":"-","text":"With geometry ready, we can run the simulation. Duration is roughly the time it takes to reach steady state, such as how long it take for the signal to reach output port. The objective is usually a steady state metric which can be computed using values from the final period. We optimize geometry for some objective. ","category":"page"},{"location":"people/#People","page":"People","title":"People","text":"","category":"section"},{"location":"people/#Community","page":"People","title":"Community","text":"","category":"section"},{"location":"people/","page":"People","title":"People","text":"Discussion & updates at Julia Discourse","category":"page"},{"location":"people/#Contributors","page":"People","title":"Contributors","text":"","category":"section"},{"location":"people/","page":"People","title":"People","text":"Paul Shen Consulting and technical support available 2024 (c) Paul Shen ","category":"page"},{"location":"#Home","page":"Home","title":"Home","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Currently Prerelease. Expect breaking changes. Report bugs on Github - we usually respond within a day","category":"page"},{"location":"#Overview","page":"Home","title":"Overview","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Generative design meets Maxwell's Equations. Differentiable FDTD package for inverse design & topology optimization in semiconductor photonics, acoustics and RF. GPU and automatic differentiation (AD) compatible. Uses AD by Zygote.jl for adjoint optimization. Integrates with Jello.jl to generate length scale controlled paramaterized geometry . Staggered Yee grid update with fully featured boundary conditions & sources. Customizable physics to potentially incorporate dynamics like heat transfer, charge transport.","category":"page"},{"location":"#Gallery","page":"Home","title":"Gallery","text":"","category":"section"},{"location":"#Quarter-wavelength-antenna-radiating-above-conductive-ground-plane","page":"Home","title":"Quarter wavelength antenna radiating above conductive ground plane","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: )","category":"page"},{"location":"#Simulation-of-coupling-into-dielectric-slab-waveguide-using-modal-source","page":"Home","title":"Simulation of coupling into dielectric slab waveguide using modal source","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: )","category":"page"},{"location":"#Simulation-of-plane-wave-scattering-on-Periodic-array","page":"Home","title":"Simulation of plane wave scattering on Periodic array","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: )","category":"page"},{"location":"#Generative-Inverse-design-of-compact-silicon-photonics-splitter","page":"Home","title":"Generative Inverse design of compact silicon photonics splitter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: )","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Install via ","category":"page"},{"location":"","page":"Home","title":"Home","text":"Pkg.add(url=\"https://github.com/paulxshen/FDTDEngine.jl\")\nPkg.add(url=\"https://github.com/paulxshen/FDTDToolkit.jl\")","category":"page"},{"location":"","page":"Home","title":"Home","text":"FDTDToolkit.jl contains visualization utilities","category":"page"},{"location":"#Quickstart","page":"Home","title":"Quickstart","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"We do a quick 3d simulation of plane wave scattering on periodic array of dielectric spheres (see gallery movie)","category":"page"},{"location":"","page":"Home","title":"Home","text":"\"\"\"\nsimulation of plane wave scattering on periodic array of dielectric spheres\n\"\"\"\n\nusing UnPack, LinearAlgebra, GLMakie\nusing FDTDEngine,FDTDToolkit\ndogpu = true\n# dogpu = false\n\nname = \"periodic_scattering\"\nT = 10 # simulation duration in [periods]\nnx = 20\ndx = 1.0 / nx # pixel resolution in [wavelengths]\n\n# geometry\nl = 2 # domain physical size length in [wavelengths]\nsz = nx .* (l, l, l) # domain voxel dimensions\nϵ1 = ϵmin = 1 #\nϵ2 = 2.25 # \nb = F.([norm(v .- sz ./ 2) < 0.5 / dx for v = Base.product(Base.oneto.(sz)...)]) # sphere\nϵ = ϵ2 * b + ϵ1 * (1 .- b)\n\n# setup\nboundaries = [Periodic(2), Periodic(3)]# unspecified boundaries default to PML\nsources = [\n PlaneWave(t -> cos(2π * t), -1; Jz=1) # Jz excited plane wave from -x plane (eg -1)\n]\nnormal = [1, 0, 0] # \nδ = 0.2 # margin\nlm = 1 # monitor side length\nmonitors = [\n Monitor([δ, l / 2, l / 2], [0, lm, lm]; normal), # (center, dimensions; normal)\n Monitor([l - δ, l / 2, l / 2], [0, lm, lm]; normal),\n]\nconfigs = setup(boundaries, sources, monitors, dx, sz; ϵmin, T)\n@unpack μ, σ, σm, dt, geometry_padding, geometry_splits, field_padding, source_instances, monitor_instances, u0, = configs\n\nϵ, μ, σ, σm = apply(geometry_padding; ϵ, μ, σ, σm)\np = apply(geometry_splits; ϵ, μ, σ, σm)\n\n# move to gpu\nif dogpu\n using CUDA, Flux\n @assert CUDA.functional()\n u0, p, field_padding, source_instances = gpu.((u0, p, field_padding, source_instances))\nend\n\n# run simulation\n@showtime u = accumulate(0:dt:T, init=u0) do u, t\n step3!(deepcopy(u), p, t, dx, dt, field_padding, source_instances)\nend\ny = [power.((m,), u) for m = monitor_instances]\n\n# move back to cpu for plotting\nif dogpu\n u, p, field_padding, source_instances = cpu.((u, p, field_padding, source_instances))\nend\n\n# make movie, \nEz = map(u) do u\n u[1][3]\nend\nϵEz = p[1][3]\ndir = @__DIR__\nrecordsim(\"$dir/$(name).mp4\", Ez, y;\n dt,\n field=:Ez,\n monitor_instances,\n source_instances,\n geometry=ϵEz,\n elevation=30°,\n playback=1,\n axis1=(; title=\"$name\\nEz\"),\n axis2=(; title=\"monitor powers\"),\n)","category":"page"}] } diff --git a/docs/tutorials/index.html b/docs/tutorials/index.html new file mode 100644 index 0000000..71a122f --- /dev/null +++ b/docs/tutorials/index.html @@ -0,0 +1,2 @@ + +Tutorials · FDTDEngine.jl
diff --git a/examples/inverse_design_signal_splitter/inverse_design_signal_splitter.jl b/examples/inverse_design_signal_splitter/inverse_design_signal_splitter.jl index 6e4c3c0..7b05ff8 100644 --- a/examples/inverse_design_signal_splitter/inverse_design_signal_splitter.jl +++ b/examples/inverse_design_signal_splitter/inverse_design_signal_splitter.jl @@ -5,12 +5,12 @@ using BSON: @save, @load using Optim: Options, minimizer using Optim using GLMakie -# using FDTDEngine,FDTDToolkit +using FDTDEngine, FDTDToolkit -dir = pwd() -include("$dir/src/main.jl") -include("$dir/../FDTDToolkit.jl/src/main.jl") -include("$dir/scripts/startup.jl") +# dir = pwd() +# include("$dir/src/main.jl") +# include("$dir/../FDTDToolkit.jl/src/main.jl") +# include("$dir/scripts/startup.jl") F = Float32 @@ -18,7 +18,6 @@ Random.seed!(1) "training params" name = "inverse_design_signal_splitter" -dogpu = true dogpu = false T = 14 # simulation duration in [periods] nbasis = 4 # complexity of design region @@ -37,11 +36,9 @@ base = F.(base) sz0 = size(ϵdummy) # "geometry generator model -@load "model.bson" model -x, re = destructure(model) - -# contrast = 10.0 -# model = Mask(round.(Int, designs[1].L / λ / dx) .+ 1, nbasis, contrast; symmetries=2) +# @load "model.bson" model +contrast = 10.0 +model = Mask(round.(Int, designs[1].L / λ / dx) .+ 1, nbasis, contrast; symmetries=2) model0 = deepcopy(model) @@ -119,28 +116,28 @@ p0 = make_geometry(model0, base, μ, σ, σm) volume(cpu(p0[1][2])) # error() -"Optim functions" -# x0, re = destructure(model) -# f_ = m -> loss(metrics(m; autodiff=false)) -# # f_ = m -> loss(metrics(m;)) -# f = f_ ∘ re -# x = deepcopy(x0) - - -# @allowscalar res = optimize(f, x, -# ParticleSwarm(; n_particles=10), -# Optim.Options(f_tol=0, iterations=20, show_every=1, show_trace=true)) -# xgf = minimizer(res) -# x = deepcopy(xgf) -# heatmap(cpu(re(x)())) -# @show metrics(re(x)) -# @save "model.bson" model = re(x) +# gradient free optimization "Optim functions +x0, re = destructure(model) +f_ = m -> loss(metrics(m; autodiff=false)) +# f_ = m -> loss(metrics(m;)) +f = f_ ∘ re +x = deepcopy(x0) + +@allowscalar res = optimize(f, x, + ParticleSwarm(; n_particles=10), + Optim.Options(f_tol=0, iterations=1, show_every=1, show_trace=true)) +xgf = minimizer(res) +x = deepcopy(xgf) +heatmap(cpu(re(x)())) +@show metrics(re(x)) +@save "model.bson" model = re(x) +model = re(x) # error() +# adjoint optimization opt = Adam(0.2) -model = re(x) opt_state = Flux.setup(opt, model) -n = 60 +n = 1 for i = 1:n @time l, (dldm,) = withgradient(m -> loss(metrics(m)), model) Flux.update!(opt_state, model, dldm) diff --git a/examples/periodic_scattering/3d_periodic_scattering.jl b/examples/periodic_scattering/3d_periodic_scattering.jl index 9b5d1d7..bb94192 100644 --- a/examples/periodic_scattering/3d_periodic_scattering.jl +++ b/examples/periodic_scattering/3d_periodic_scattering.jl @@ -3,15 +3,14 @@ simulation of plane wave scattering on periodic array of dielectric spheres """ using UnPack, LinearAlgebra, GLMakie -# using FDTDEngine,FDTDToolkit -dir = pwd() -include("$(dir)/src/main.jl") -include("$(dir)/scripts/startup.jl") -include("$dir/../FDTDToolkit.jl/src/main.jl") +using FDTDEngine, FDTDToolkit -dogpu = true -# dogpu = false +# dir = pwd() +# include("$(dir)/src/main.jl") +# include("$(dir)/scripts/startup.jl") +# include("$dir/../FDTDToolkit.jl/src/main.jl") +dogpu = true name = "periodic_scattering" T = 10 # simulation duration in [periods] nx = 20 diff --git a/examples/slab_waveguide/slab_waveguide.jl b/examples/slab_waveguide/slab_waveguide.jl index c3442a8..ec6380e 100644 --- a/examples/slab_waveguide/slab_waveguide.jl +++ b/examples/slab_waveguide/slab_waveguide.jl @@ -4,18 +4,16 @@ simulation of coupling into dielectric slab waveguide using modal source using UnPack, LinearAlgebra, GLMakie using BSON: @load -# using FDTDEngine,FDTDToolkit +using FDTDEngine, FDTDToolkit -dir = pwd() -include("$(dir)/src/main.jl") -include("$(dir)/scripts/startup.jl") -include("$dir/../FDTDToolkit.jl/src/main.jl") +# dir = pwd() +# include("$(dir)/src/main.jl") +# include("$(dir)/scripts/startup.jl") +# include("$dir/../FDTDToolkit.jl/src/main.jl") dogpu = true -# dogpu = false - name = "slab_waveguide" -T = 10 # simulation duration in [periods] +T = 14 # simulation duration in [periods] # load mode profile and waveguide dimensions from results of external mode solver @load "$(@__DIR__)/modes.bson" modes lb ub λ dx hsub wwg hwg hclad w h ϵsub ϵclad ϵwg @@ -71,7 +69,7 @@ end @showtime u = accumulate(0:dt:T, init=u0) do u, t step3!(deepcopy(u), p, t, dx, dt, field_padding, source_instances) end -y = [power.((m,), u) for m = monitor_instances] +v = [power.((m,), u) for m = monitor_instances] # move back to cpu for plotting if dogpu @@ -85,7 +83,7 @@ Ey = map(u) do u end ϵEy = p[1][i] dir = @__DIR__ -recordsim("$dir/$(name).mp4", Ey, y; +recordsim("$dir/$(name).mp4", Ey, v; dt, field=:Ey, monitor_instances, diff --git a/examples/slab_waveguide/slab_waveguide.mp4 b/examples/slab_waveguide/slab_waveguide.mp4 index 007e8b2..c982028 100644 Binary files a/examples/slab_waveguide/slab_waveguide.mp4 and b/examples/slab_waveguide/slab_waveguide.mp4 differ diff --git a/makedocs/make.jl b/makedocs/make.jl index 597e78e..bd50913 100644 --- a/makedocs/make.jl +++ b/makedocs/make.jl @@ -8,6 +8,9 @@ makedocs( # modules=[FDTDEngine], pages=[ "index.md", + "guide.md", + "tutorials.md", + "people.md", ] ) diff --git a/makedocs/src/assets/guide copy.md b/makedocs/src/assets/guide copy.md new file mode 100644 index 0000000..793e83f --- /dev/null +++ b/makedocs/src/assets/guide copy.md @@ -0,0 +1,11 @@ +## + +Engineers run simulations to improve designs. Each time the design changes, the simulation is re-run. This can be done systematically in "parameter sweeps" where different combinations of parameter values are simulated to determine the best design. However, this scales exponentially wrt the number of parameters or DOFs. + +## General workflow +We use gradient descent, the same as in machine learning. In lieu of optimizing neural network parameters, we're optimizing geometry (or source) parameters. In each training iteration, we generate geometry, run the simulation, calculate the objective metric, and do a backward pass to derive the gradient wrt the geometry parameters. We then do a gradient based parameter update in preparation for the next iteration. + +The geometry is thus the first step3. It typically has a static component which we can't change such as interfacing waveguides. Then there's a design component which we can change or optimize. The user is responsible for generating the design geometry wrt design parameters. If any pattern is allowed in the design region, our sister package `Jello.jl` can be used as a length scale controlled geometry generator. In any case, the result needs to be a 2d/3d array of each relevant materials property eg permitivity. + +With geometry ready, we can run the simulation. Duration is roughly the time it takes to reach steady state, such as how long it take for the signal to reach output port. The objective is usually a steady state metric which can be computed using values from the final period. +We optimize geometry for some objective. \ No newline at end of file diff --git a/makedocs/src/assets/index copy 2.md b/makedocs/src/assets/index copy 2.md new file mode 100644 index 0000000..e69de29 diff --git a/makedocs/src/guide.md b/makedocs/src/guide.md index dd8288a..82f32b2 100644 --- a/makedocs/src/guide.md +++ b/makedocs/src/guide.md @@ -1,11 +1,41 @@ -## +# Guide +## Implementation + Length and time are in units of wavelength and period. This normalization allows usage of relative permitivity and permeability in equations . Fields including electric, magnetic and current density are simply bundled as a vector of vectors of arrays . Boundary conditions pad the field arrays . PML paddings are multilayered, while All other boundaries add single layers. Paddings are stateful and permanent, increasing the size of field and geometry arrays. Finite differencing happens every update step3 and are coordinated to implictly implement a staggered Yee's grid . -Engineers run simulations to improve designs. Each time the design changes, the simulation is re-run. This can be done systematically in "parameter sweeps" where different combinations of parameter values are simulated to determine the best design. However, this scales exponentially wrt the number of parameters or DOFs. +## Sources +If a source has fewer nonzero dimensions than the simulation domain, its signal will get normalized along its singleton dimensions. For example, all planar sources in 3d or line sources in 2d will get scaled up by a factor of `1/dx`. This way, discretisation would not affect radiated power. +```@docs +PlaneWave +Source +``` -## General workflow -We use gradient descent, the same as in machine learning. In lieu of optimizing neural network parameters, we're optimizing geometry (or source) parameters. In each training iteration, we generate geometry, run the simulation, calculate the objective metric, and do a backward pass to derive the gradient wrt the geometry parameters. We then do a gradient based parameter update in preparation for the next iteration. +## Boundaries +Unspecified boundaries default to PML +```@docs +Periodic +PML +PEC +PMC +``` +## Monitors + ```@docs +Monitor +power +power_density +``` -The geometry is thus the first step3. It typically has a static component which we can't change such as interfacing waveguides. Then there's a design component which we can change or optimize. The user is responsible for generating the design geometry wrt design parameters. If any pattern is allowed in the design region, our sister package `Jello.jl` can be used as a length scale controlled geometry generator. In any case, the result needs to be a 2d/3d array of each relevant materials property eg permitivity. - -With geometry ready, we can run the simulation. Duration is roughly the time it takes to reach steady state, such as how long it take for the signal to reach output port. The objective is usually a steady state metric which can be computed using values from the final period. -We optimize geometry for some objective. \ No newline at end of file + ## Physics +```@docs +step3! +step3 +``` +## GPU support +Simply use `Flux.gpu` to move simulation variables to GPU. This turns `Arrays` into CUDA arrays which get processed on GPU for both forward and backpropagation passes +## Automatic differentiation adjoints +Compatible with `Zygote.jl` and `Flux.jl`. Please use `step3` instead of `step3!` when doing AD. See inverse design examples +## Generative inverse design +Please contact us for latest scripts. We wrote [Jello.jl](https://github.com/paulxshen/Jello.jl), an innovative Fourier domain neural model to generate length scale controlled efficiently paramaterized geometry . +## Comparison with other FDTD software +Our focus is on inverse design and topology optimization using adjoints from automatic differentiation. We love a streamlined API backed by a clear, concise and extensible codebase. Attention is paid to speed and malloc but that's not our main concern. +Meep is the most popular open source FDTD package owing to its maturity and comprehensive features. It supports AD in certain cases using custom adjoints which we avoid in our package in favor of more flexibility . +There are numerous commercial software eg Ansys Lumerical, Comsol and various EDA or SI software. TMK none of them supports AD for inverse design diff --git a/makedocs/src/index.md b/makedocs/src/index.md index 27cc260..b62785d 100644 --- a/makedocs/src/index.md +++ b/makedocs/src/index.md @@ -1,7 +1,7 @@ # Home - Currently Prerelease. Expect breaking changes. Report bugs on (Github )[ https://github.com/paulxshen/FDTDEngine.jl] - we usually respond within a day + Currently Prerelease. Expect breaking changes. Report bugs on [Github](https://github.com/paulxshen/FDTDEngine.jl) - we usually respond within a day ## Overview -Generative design meets Maxwell's Equations. Differentiable FDTD package for inverse design & topology optimization in semiconductor photonics, acoustics and RF. GPU and automatic differentiation (AD) compatible. Uses AD by `Zygote.jl` for adjoint optimization. Integrates with `Jello.jl` to generate length scale controlled paramaterized geometry . Staggered Yee grid update with fully featured boundary conditions & sources. Customizable physics to potentially incorporate dynamics like heat transfer, charge transport. +Generative design meets Maxwell's Equations. Differentiable FDTD package for inverse design & topology optimization in semiconductor photonics, acoustics and RF. GPU and automatic differentiation (AD) compatible. Uses AD by `Zygote.jl` for adjoint optimization. Integrates with [`Jello.jl`](https://github.com/paulxshen/Jello.jl) to generate length scale controlled paramaterized geometry . Staggered Yee grid update with fully featured boundary conditions & sources. Customizable physics to potentially incorporate dynamics like heat transfer, charge transport. ## Gallery ### Quarter wavelength antenna radiating above conductive ground plane ![](assets/quarter_wavelength_antenna.mp4) @@ -27,37 +27,34 @@ simulation of plane wave scattering on periodic array of dielectric spheres """ using UnPack, LinearAlgebra, GLMakie -# using FDTDEngine,FDTDToolkit -dir = pwd() -include("$(dir)/src/main.jl") -include("$dir/../FDTDToolkit.jl/src/main.jl") +using FDTDEngine,FDTDToolkit +dogpu = true +# dogpu = false +name = "periodic_scattering" +T = 10 # simulation duration in [periods] +nx = 20 +dx = 1.0 / nx # pixel resolution in [wavelengths] -name = "3d_scattering" -T = 8.0f0 # simulation duration in [periods] -nx = 16 -dx = 1.0f0 / nx # pixel resolution in [wavelengths] - -"geometry" -l = 2 # domain physical size length +# geometry +l = 2 # domain physical size length in [wavelengths] sz = nx .* (l, l, l) # domain voxel dimensions ϵ1 = ϵmin = 1 # -ϵ2 = 2.25f0 # +ϵ2 = 2.25 # b = F.([norm(v .- sz ./ 2) < 0.5 / dx for v = Base.product(Base.oneto.(sz)...)]) # sphere ϵ = ϵ2 * b + ϵ1 * (1 .- b) -"setup" +# setup boundaries = [Periodic(2), Periodic(3)]# unspecified boundaries default to PML sources = [ - PlaneWave(t -> cos(F(2π) * t), -1; Jz=1) # Jz excited plane wave from -x plane (eg -1) + PlaneWave(t -> cos(2π * t), -1; Jz=1) # Jz excited plane wave from -x plane (eg -1) ] -n = [1, 0, 0] # normal -δ = 0.2f0 # margin -# A = (l - δ)^2 +normal = [1, 0, 0] # +δ = 0.2 # margin lm = 1 # monitor side length monitors = [ - Monitor([δ, l / 2, l / 2], [0, lm, lm], n,), # (center, dimensions, normal) - Monitor([l - δ, l / 2, l / 2], [0, lm, lm], n,), + Monitor([δ, l / 2, l / 2], [0, lm, lm]; normal), # (center, dimensions; normal) + Monitor([l - δ, l / 2, l / 2], [0, lm, lm]; normal), ] configs = setup(boundaries, sources, monitors, dx, sz; ϵmin, T) @unpack μ, σ, σm, dt, geometry_padding, geometry_splits, field_padding, source_instances, monitor_instances, u0, = configs @@ -65,88 +62,39 @@ configs = setup(boundaries, sources, monitors, dx, sz; ϵmin, T) ϵ, μ, σ, σm = apply(geometry_padding; ϵ, μ, σ, σm) p = apply(geometry_splits; ϵ, μ, σ, σm) +# move to gpu +if dogpu + using CUDA, Flux + @assert CUDA.functional() + u0, p, field_padding, source_instances = gpu.((u0, p, field_padding, source_instances)) +end # run simulation -t = 0:dt:T -u = [[similar.(a) for a = u0] for t = t] -u[1] = u0 -@showtime reduce( - (u, (u1, t)) -> step3!(u1, u, p, t, dx, dt, field_padding, source_instances), - zip(u[2:end], t[1:end-1]), - init=u0) -y = hcat([power.((m,), u) for m = monitor_instances]...) +@showtime u = accumulate(0:dt:T, init=u0) do u, t + step3!(deepcopy(u), p, t, dx, dt, field_padding, source_instances) +end +y = [power.((m,), u) for m = monitor_instances] -# make movie +# move back to cpu for plotting +if dogpu + u, p, field_padding, source_instances = cpu.((u, p, field_padding, source_instances)) +end + +# make movie, Ez = map(u) do u u[1][3] end -ϵz = p[1][3] +ϵEz = p[1][3] dir = @__DIR__ - -recordsim("$dir/$(name)_nres_$nx.mp4", Ez, y; +recordsim("$dir/$(name).mp4", Ez, y; dt, + field=:Ez, monitor_instances, source_instances, - geometry=ϵz, + geometry=ϵEz, elevation=30°, playback=1, axis1=(; title="$name\nEz"), axis2=(; title="monitor powers"), ) - -``` -# Guide -## Implementation - - Length and time are in units of wavelength and period. This normalization allows usage of relative permitivity and permeability in equations . Fields including electric, magnetic and current density are simply bundled as a vector of vectors of arrays . Boundary conditions pad the field arrays . PML paddings are multilayered, while All other boundaries add single layers. Paddings are stateful and permanent, increasing the size of field and geometry arrays. Finite differencing happens every update step3 and are coordinated to implictly implement a staggered Yee's grid . - -## Sources -If a source has fewer nonzero dimensions than the simulation domain, its signal will get normalized along its singleton dimensions. For example, all planar sources in 3d or line sources in 2d will get scaled up by a factor of `1/dx`. This way, discretisation would not affect radiated power. -```@docs -PlaneWave -Source -``` - - -## Boundaries -Unspecified boundaries default to PML -```@docs -Periodic -PML -PEC -PMC -``` -## Monitors - ```@docs -Monitor -power -power_density -``` - - ## Physics -```@docs -step3! -step3 ``` - - - -## GPU support -Simply use `Flux.gpu` to move simulation variables to GPU. This turns `Arrays` into CUDA arrays which get processed on GPU for both forward and backpropagation passes -## Automatic differentiation adjoints -Compatible with `Zygote.jl` and `Flux.jl`. Please use `step3` instead of `step3!` when doing AD. See inverse design examples -## Generative inverse design -Please contact us for latest scripts. We wrote (Jello.jl)[https://github.com/paulxshen/Jello.jl], an innovative Fourier domain neural model to generate length scale controlled efficiently paramaterized geometry . -## Comparison with other FDTD software -Our focus is on inverse design and topology optimization using adjoints from automatic differentiation. We love a streamlined API backed by a clear, concise and extensible codebase. Attention is paid to speed and malloc but that's not our main concern. -Meep is the most popular open source FDTD package owing to its maturity and comprehensive features. It supports AD in certain cases using custom adjoints which we avoid in our package in favor of more flexibility . -There are numerous commercial software eg Ansys Lumerical, Comsol and various EDA or SI software. TMK none of them supports AD for inverse design -# Tutorials -see (`examples/`)[https://github.com/paulxshen/FDTDEngine.jl/blob/main/examples/] -# People -## Community -Discussion & updates at [Julia Discourse](https://discourse.julialang.org/t/pre-ann-differentiable-fdtd-for-inverse-design-in-photonics-acoustics-and-rf/105405/12) -## Contributors -Paul Shen -Consulting and technical support available -2024 (c) Paul Shen \ No newline at end of file diff --git a/makedocs/src/people.md b/makedocs/src/people.md new file mode 100644 index 0000000..8986100 --- /dev/null +++ b/makedocs/src/people.md @@ -0,0 +1,7 @@ +# People +## Community +Discussion & updates at [Julia Discourse](https://discourse.julialang.org/t/pre-ann-differentiable-fdtd-for-inverse-design-in-photonics-acoustics-and-rf/105405/12) +## Contributors +Paul Shen +Consulting and technical support available +2024 (c) Paul Shen \ No newline at end of file diff --git a/makedocs/src/tutorials.md b/makedocs/src/tutorials.md new file mode 100644 index 0000000..8804181 --- /dev/null +++ b/makedocs/src/tutorials.md @@ -0,0 +1,2 @@ +# Tutorials +see [`examples/`](https://github.com/paulxshen/FDTDEngine.jl/blob/main/examples/)