-
Notifications
You must be signed in to change notification settings - Fork 10
/
search_index.js
3 lines (3 loc) · 72.7 KB
/
search_index.js
1
2
3
var documenterSearchIndex = {"docs":
[{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"EditURL = \"https://github.com/JuliaClimate/IndividualDisplacements.jl/blob/master/examples/worldwide/global_ocean_circulation.jl\"","category":"page"},{"location":"worldwide/global_ocean_circulation/#Global-Climatology","page":"Global Climatology","title":"Global Climatology","text":"","category":"section"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"(Image: ) (Image: )","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"Advect particles with climatological monthly mean flow at selected depth level (e.g. k=10 for 95 m) from a global ocean state estimate (ECCO v4 r2 ; see also https://ecco-group.org) which is here repeated for ny years. For additional documentation e.g. see : 1, 2, 3, 4","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"(Image: simulated particle movie (5m))","category":"page"},{"location":"worldwide/global_ocean_circulation/#.-Get-Software-and-Iput-Files","page":"Global Climatology","title":"1. Get Software & Iput Files","text":"","category":"section"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"packages + helper functions\ngrid and velocity files","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"using IndividualDisplacements, DataFrames, Statistics, CSV\n\ninclude(joinpath(dirname(pathof(IndividualDisplacements)),\"../examples/helper_functions.jl\"))\nIndividualDisplacements.get_ecco_velocity_if_needed();\nnothing #hide","category":"page"},{"location":"worldwide/global_ocean_circulation/#.-Set-Up-Parameters-and-Inputs","page":"Global Climatology","title":"2. Set Up Parameters & Inputs","text":"","category":"section"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"select vertical level (k=1 by default; k=0 for 3D) & duration in years (ny=2 by default)\nread grid variables\nreturn FlowFields (𝑃) and ancillary variables etc (𝐷)\nread & normalize velocities (𝐷.🔄)","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"𝑃,𝐷=global_ocean_circulation(k=1,ny=2);\n\n𝐷.🔄(𝑃,𝐷,0.0)\n\nfieldnames(typeof(𝑃))","category":"page"},{"location":"worldwide/global_ocean_circulation/#.-Main-Computation-Loop","page":"Global Climatology","title":"3. Main Computation Loop","text":"","category":"section"},{"location":"worldwide/global_ocean_circulation/#.1-Initialize-Individuals-and-Solution","page":"Global Climatology","title":"3.1 Initialize Individuals & Solution","text":"","category":"section"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"initial particle positions randomly over Global Ocean","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"np=100\n\n#xy = init_global_randn(np,𝐷)\n#df=DataFrame(x=xy[1,:],y=xy[2,:],f=xy[3,:])\n\np=dirname(pathof(IndividualDisplacements))\nfil=joinpath(p,\"../examples/worldwide/global_ocean_circulation.csv\")\ndf=DataFrame(CSV.File(fil))\n\n𝐼=Individuals(𝑃,df.x[1:np],df.y[1:np],df.f[1:np])\nfieldnames(typeof(𝐼))","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"initial integration from time 0 to 0.5 month","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"📌ini=deepcopy(𝐼.📌)\n𝑇=(0.0,𝐼.𝑃.𝑇[2])\n∫!(𝐼,𝑇)","category":"page"},{"location":"worldwide/global_ocean_circulation/#.2-Iteration-function-example","page":"Global Climatology","title":"3.2 Iteration function example","text":"","category":"section"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"In addition, step! is defined to provide additional flexibility around ∫! :","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"𝐷.🔄(𝐼.𝑃,t_ϵ) resets the velocity input streams to bracket t_ϵ=𝐼.𝑃.𝑇[2]+eps(𝐼.𝑃.𝑇[2])\nreset_📌!(𝐼) randomly selects a fraction (𝐷.frac) of the particles and resets their positions before each integration period. This tends to maintain homogeneous coverage of the Global Ocean by particles.\n∫!(𝐼) then solves for the individual trajectories over one month, with updated velocity fields (𝐼.𝑃.u0 etc), and adds diagnostics to the DataFrame used to record variables along the trajectory (𝐼.🔴).","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"function step!(𝐼::Individuals)\n t_ϵ=𝐼.𝑃.𝑇[2]+eps(𝐼.𝑃.𝑇[2])\n 𝐷.🔄(𝐼.𝑃,𝐷,t_ϵ)\n reset_📌!(𝐼,𝐷.frac,📌ini)\n ∫!(𝐼)\nend","category":"page"},{"location":"worldwide/global_ocean_circulation/#.3-Iterate-For-ny*12-Months","page":"Global Climatology","title":"3.3 Iterate For ny*12 Months","text":"","category":"section"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"[step!(𝐼) for y=1:1, m=1:1]\n\nadd_lonlat!(𝐼.🔴,𝐷.XC,𝐷.YC);\nnothing #hide","category":"page"},{"location":"worldwide/global_ocean_circulation/#.4-Compute-summary-statistics","page":"Global Climatology","title":"3.4 Compute summary statistics","text":"","category":"section"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"See DataFrames.jl documentation for detail and additinal functionalities.","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"gdf = groupby(𝐼.🔴, :ID)\nsgdf= combine(gdf,nrow,:lat => mean)\nsgdf[rand(1:size(sgdf,1),4),:]","category":"page"},{"location":"worldwide/global_ocean_circulation/#.-Plot-trajectories-/-individual-positions","page":"Global Climatology","title":"4. Plot trajectories / individual positions","text":"","category":"section"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"using Plots\np=plot(;xlims=(-180,180),ylims=(-90,90),legend=:none)\np!(x,y)=scatter!(p,x,y,markersize=1.1,markerstrokewidth=0)\n[p!(gdf[i].lon,gdf[i].lat) for i in rand(collect(1:length(gdf)),10)]\ndisplay(p)","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"Or select a background map (e.g. lon, lat, and DL=log10(bottom depth)) and a recipe to superimpose initial and final locations. Try:","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"include(joinpath(dirname(pathof(IndividualDisplacements)),\"../examples/recipes_plots.jl\"))\nmap(𝐼,OceanDepthLog(𝐷.Γ))","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"","category":"page"},{"location":"worldwide/global_ocean_circulation/","page":"Global Climatology","title":"Global Climatology","text":"This page was generated using Literate.jl.","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"EditURL = \"https://github.com/JuliaClimate/IndividualDisplacements.jl/blob/master/examples/basics/solid_body_rotation.jl\"","category":"page"},{"location":"basics/solid_body_rotation/#Three-Dimensions","page":"Three Dimensions","title":"Three Dimensions","text":"","category":"section"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"(Image: ) (Image: )","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"Simulate the trajectory of an individual point, first in a perfectly circular flow (a.k.a. solid body rotation). Then add a convergent term to obtain a spiraling trajectory, and a constant vertical velocity for the third dimension. These simple flow configurations can be thought of as idealized models e.g. ocean meso-scale eddies.","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"For additional documentation e.g. see : 1, 2, 3, 4","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"Exercise examples:","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"make the sinking velocity decrease with time (hint: it increases in the original notebook)\nchange the number of times the particle goes around the origin","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"(Image: solid body rotation)","category":"page"},{"location":"basics/solid_body_rotation/#Problem-Configuration","page":"Three Dimensions","title":"1 Problem Configuration","text":"","category":"section"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"Here we set up software, grid, flow fields, initial conditions.","category":"page"},{"location":"basics/solid_body_rotation/#.1-Import-Software","page":"Three Dimensions","title":"1.1 Import Software","text":"","category":"section"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"using IndividualDisplacements, DataFrames\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/flow_fields.jl\"))","category":"page"},{"location":"basics/solid_body_rotation/#.2-Flow-Fields","page":"Three Dimensions","title":"1.2 Flow Fields","text":"","category":"section"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"The simple_flow_field function (defined in helper_functions.jl) defines a simple three-dimensional flow field. Exercise: locate simple_flow_field and modify the flow field parameters (e.g. intensity and sign of the convergent term).","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"np,nz=16,4 #gridded domain size (horizontal and vertical)\n\nu,v,w=solid_body_rotation(np,nz) #staggered velocity arrays\n\n𝐹=FlowFields(u,u,v,v,0*w,1*w,[0,19.95*2*pi]); #FlowFields data structure\nnothing #hide","category":"page"},{"location":"basics/solid_body_rotation/#.3-Initialize-Individuals","page":"Three Dimensions","title":"1.3 Initialize Individuals","text":"","category":"section"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"Let's just set up one individual at [np1/3,np1/3,nz*1/3] in the three-dimensional space where the flow fields have been configured","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"(x,y,z)=(np*1/3,np*1/3,nz*1/3)\n\n𝐼=Individuals(𝐹,x,y,z)","category":"page"},{"location":"basics/solid_body_rotation/#.4-A-Closer-Look-(optional)","page":"Three Dimensions","title":"1.4 A Closer Look (optional)","text":"","category":"section"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"The above Individuals constructor wraps up 𝐹, the initial position, and other needed components within 𝐼. At this point, you can either jump to section 2 or read through this section to learn more about how the details as needed e.g. if you wanted to overide default options that were selected for you by the section 1.3 constructor.","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"Initial position is","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"📌=[x,y,z]","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"and the data structure (DataFrame) to record properties along the individual's path accordingly.","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"🔴 = DataFrame(ID=Int[], x=Float64[], y=Float64[], z=Float64[], t=Float64[])","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"It is the postprocessing function's responsibility to provide the record. It is thus important that this intermediary (postproc) be consistent with the solver setup (sol) and the expected record format (🔴).","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"function postproc(sol,𝐹::FlowFields;id=missing,𝑇=missing)\n df=postprocess_xy(sol,𝐹,id=id,𝑇=𝑇)\n #add third coordinate\n z=sol[3,:]\n df.z=z[:]\n return df\nend","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"The velocity function 🚄 relies only on flow fields obtained from 𝐹 (which is defined above) to interpolate velocity at the specified space-time position (e.g. those of individuals).","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"🚄 = dxdt!","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"Now that every thing needed to carry out the computation is in place, we wrap up the problem configuration in a struct (Individuals) which links to the initial positions, flow fields, etc. all that will be necessary to compute trajectories over time (∫!(𝐼,𝑇)).","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"#assemble as a NamedTuple:\nI=(position=📌,record=🔴,velocity=🚄,\npostprocessing=postproc,parameters=𝐹)\n\n#construct Individuals from NamedTuple:\n𝐼=Individuals(I)","category":"page"},{"location":"basics/solid_body_rotation/#Trajectory-Simulations","page":"Three Dimensions","title":"2 Trajectory Simulations","text":"","category":"section"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"The ∫! function call below returns the final positions & updates 𝐼.📌 accordingly. It also records properties observed along the trajectory in 𝐼.🔴. Simple methods to visualize the individual trajectory (plot or movie) are provided at the end.","category":"page"},{"location":"basics/solid_body_rotation/#.1-Compute-Trajectories","page":"Three Dimensions","title":"2.1 Compute Trajectories","text":"","category":"section"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"𝑇=(0.0,𝐼.𝑃.𝑇[2])\n∫!(𝐼,𝑇)","category":"page"},{"location":"basics/solid_body_rotation/#.2-Visualize-Trajectories","page":"Three Dimensions","title":"2.2 Visualize Trajectories","text":"","category":"section"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"define myplot convenience function\nsingle plot example using myplot\n(generate animation using myplot)","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"p=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/recipes_plots.jl\"));\nnt=length(𝐼.🔴.x)\n\nmyplot(i)=plot(𝐼.🔴.x[1:i],𝐼.🔴.y[1:i],𝐼.🔴.z[1:i],linewidth=2,arrow = 2,\n title=\"Solid body rotation / Spiral example\",leg=false,\n xaxis=\"x\",yaxis=\"y\",zaxis=\"z\",xlims=(0,np),ylims=(0,np));\nnothing #hide","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"Single plot example:","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"plt=myplot(nt)\nscatter!(plt,[📌[1]],[📌[2]],[📌[3]])\n#scatter!(plt,[𝐼.🔴.x[end]],[𝐼.🔴.y[end]],[𝐼.🔴.z[end]])\nscatter!(plt,[𝐼.📌[1]],[𝐼.📌[2]],[𝐼.📌[3]])","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"Animation example:","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"p=Int(ceil(nt/100))\nanim = @animate for i ∈ 1:p:nt\n myplot(i)\nend\n\npth=tempdir()*\"/\"\ngif(anim, pth*\"SolidBodyRotation.gif\", fps = 15)","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"","category":"page"},{"location":"basics/solid_body_rotation/","page":"Three Dimensions","title":"Three Dimensions","text":"This page was generated using Literate.jl.","category":"page"},{"location":"examples/#Summary","page":"Example Guide","title":"Summary","text":"","category":"section"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"The four examples outlined below form a tutorial of sort, and thus complement the rest of the package documentation. The corresponing data wrangling examples in flow_fields.jl define grids and ingest velocity fields. They hopefully provide a useful jumping off point in order to configure IndividualDisplacements.jl for new problems.","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"Output is in DataFrames tabular format which comes with powerful and convenient analysis methods. Plotting results in space and time can be done as in recipes_plots.jl, recipes_makie.jl, and recipes_pyplot.jl – see the examples.","category":"page"},{"location":"examples/#Particle-Set-Example","page":"Example Guide","title":"Particle Set Example","text":"","category":"section"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"Simulation of an ensemble of displacements (and trajectories) in a simple 2D configuration. ","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"The convert_to_FlowFields convenience function defines a simplified gridded domain that matches the velocity array size, adds a time range, and returns a FlowFields data structure 𝐹. All that is left to do at this stage is to define initial conditions, put them together with 𝐹 within the Individuals data structure 𝐼, and call ∫!(𝐼).","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"The prototype for this example is based on a randomly generated flow field in a doubly periodic gridded domain. Exercises include the non-periodic domain case, statistics made easy via DataFrames.jl, and replacing the flow field with your own.","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"(Image: RandomFlow)","category":"page"},{"location":"examples/#Single-Particle-Example","page":"Example Guide","title":"Single Particle Example","text":"","category":"section"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"Setup a three-dimensional flow field u,v,w, initialize a single particle / individual position 📌, and wrap everything up within an Individuals data structure 𝐼.","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"𝐼 is displaced by integrating the individual velocity, moving along through space, over time 𝑇. This is the main computation done in this package – interpolating u,v,w to individual positions 𝐼.📌 on the fly, using 𝐼.🚄, and integrating through time, using 𝐼.∫.","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"The flow field consists of rigid body rotation, plus a convergent term, plus a sinking term in the vertical direction. This flow field generates a downward, converging spiral – a idealized version of a relevant case in the Ocean.","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"(Image: SolidBodyRotation)","category":"page"},{"location":"examples/#Global-Ocean-Circulation","page":"Example Guide","title":"Global Ocean Circulation","text":"","category":"section"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"A simulation of floating particles over the Global Ocean which illustrates (1) using time variable velocity fields, (2) global connections, (3) particle re-seeding, and (4) output statistics. ","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"The flow field is based on a data-constrained ocean model solution. The problem is configured in a way to mimic, albeit very crudely, the near-surface tranport of plastics or planktons.","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"(Image: simulated particle movie (5m))","category":"page"},{"location":"examples/#Three-Dimensional-Pathways","page":"Example Guide","title":"Three Dimensional Pathways","text":"","category":"section"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"A simulation of particles that follow the three-dimensional ocean circulation. This example illustrates (1) the 3D case in a relatistic configuration, (2) tracking the advent or origin of a water patch, and (3) multifacted visualizations in 3D.","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"The flow field is based on a data-constrained, realistic, ocean model. The problem configuration mimics, albeit very approximately, ocean tracers / coumpounds transported by water masses .","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"(Image: simulated particle movie (3D))","category":"page"},{"location":"examples/#Running-The-Examples","page":"Example Guide","title":"Running The Examples","text":"","category":"section"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"Running the examples requires julia and its relevant packages. Inputs get downloaded as needed upon running the examples. The following commands ought to run on either your local computer or e.g here in the cloud.","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"Maybe the simplest option is to generate jupyter notebooks for all examples as part of the documentation build (see below). The generated notebooks should be easy to re-run afterwards. To generate and run the notebooks, start julia in the terminal or a jupyter notebook at the IndividualDisplacements.jl/ folder. Then try:","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"using Pkg\nPkg.activate(\"docs/\")\nPkg.instantiate()\nPkg.add(path=\"./\")\ninclude(\"docs/make.jl\")","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"Or alternatively, to generate notebooks with more detailed control:","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"using Literate\nset1 = [\"solid_body_rotation\",\"random_flow_field\",\"detailed_look\",\"particle_cloud\"]\n[Literate.notebook(\"examples/basics/\"*i*\".jl\", \".\", execute = true, documenter = false) for i in set1]\nset2 = [\"global_ocean_circulation\",\"three_dimensional_ocean\"]\n[Literate.notebook(\"examples/worldwide/\"*i*\".jl\", \".\", execute = true, documenter = false) for i in set2] ","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"Or as another alternative one can simply run the julia source file:","category":"page"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"using IndividualDisplacements\np=dirname(pathof(IndividualDisplacements))\ninclude(p*\"/../examples/worldwide/global_ocean_circulation.jl\")","category":"page"},{"location":"examples/#More-Examples","page":"Example Guide","title":"More Examples","text":"","category":"section"},{"location":"examples/","page":"Example Guide","title":"Example Guide","text":"Examples reproducing trajectories that had been computed earlier in Fortran (MITgcm/pkg/flt) are detailed_look.jl and particle_cloud.jl. \nFor more examples, see: example_CyclicArray.jl, example123.jl, helper_functions.jl.","category":"page"},{"location":"workflow/#Typical-Workflow","page":"User Guide","title":"Typical Workflow","text":"","category":"section"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"As documented in the examples, the typical worflow is:","category":"page"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"set up FlowFields data structure\nset up Individuals with initial position 📌\ndisplace Individuals according to FlowFields (via\t∫! and 🚄)\npost-process and record results (via 🔧 and 🔴)\ngo back to step 2 and continue if needed","category":"page"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"Steps 1 and 2 are done via data structures documented below. Both steps 3 and step 4 often take place within the call to ∫!which can readily post-process results via 🔧 before recording them in 🔴 and finally updating positions 📌. Since 🔴 is in the DataFrames tabular format, it is easily manipulated, plotted, or saved after the fact (step 4 per se).","category":"page"},{"location":"workflow/#Scope-And-Examples","page":"User Guide","title":"Scope And Examples","text":"","category":"section"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"A central goal of this package is to support scientific analysis of climate model output and observed drifts of e.g. plastics in the Ocean or chemical coumpounds in the Atmosphere. As an initial step, the package supports all types of gridded model output (on Arakawa C-grids) from the MIT General Circulation Model via the MeshArrays.jl package (docs found here). ","category":"page"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"By convention, IndividualDisplacements.jl expects input flow fields to be provided in a uniform fashion: (1) normalized to grid index units (i.e. in 1/s rather than m/s units); (2) positive towards increasing indices; (3) using the Arakawa C-grid, with u (resp v) staggered by -0.5 point in direction 1 (resp 2) from grid cell centers. ","category":"page"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"The examples document simple methods to prepare and ingest such flow fields (time varying or not; in 2D or 3D) and derive individual displacements / trajectories from them. They cover simple grids often used in process studies, Global Ocean simulations normally done on more complex grids, plotting tools, and data formats. ","category":"page"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"For an overview of the examples, please refer to the example guide. The rest of this section is focused on the package's data structures and core functions.","category":"page"},{"location":"workflow/#Data-Structures","page":"User Guide","title":"Data Structures","text":"","category":"section"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"The Individuals struct contains a FlowFields struct (incl. e.g. arrays), initial positions for the individuals, and the other elements (e.g. functions) involved in ∫!(𝐼,𝑇) as documented hereafter.","category":"page"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"Modules = [IndividualDisplacements]\nOrder = [:type]","category":"page"},{"location":"workflow/#IndividualDisplacements.FlowFields","page":"User Guide","title":"IndividualDisplacements.FlowFields","text":"abstract type FlowFields\n\nData structure that provide access to flow fields (gridded as arrays) which will be used to interpolate velocities to individual locations later on (once embedded in an Individuals struct). \n\nFollowing the C-grid convention also used in MITgcm (https://mitgcm.readthedocs.io) flow fields are expected to be staggered as follows: grid cell i,j has its center located at i-1/2,j-1/2 while the corresponding u[i,j] (resp. `v[i,j]) is located at i-1,j-1/2 (resp. i-1/2,j-1). \n\nAlso by convention, velocity fields are expected to have been normalized to grid units (e.g. 1/s rather than m/s) before sending them to one of the supported FlowFields constructors (using either Array or MeshArray):\n\n𝐹_Array2D(u0,u1,v0,v1,𝑇)\n𝐹_Array3D(u0,u1,v0,v1,w0,w1,𝑇)\n𝐹_MeshArray2D(u0,u1,v0,v1,𝑇,update_location!)\n𝐹_MeshArray3D(u0,u1,v0,v1,w0,w1,𝑇,update_location!)\n\nUsing the FlowFields constructor which gets selected by the type of u0 etc. For example :\n\n𝐹=FlowFields(u,u,v,v,0*w,1*w,[0.0,10.0])\n𝐹=FlowFields(u,u,v,v,[0.0,10.0],func)\n\nas shown in the online documentation examples.\n\n\n\n\n\n","category":"type"},{"location":"workflow/#IndividualDisplacements.Individuals","page":"User Guide","title":"IndividualDisplacements.Individuals","text":"struct Individuals{T,N}\n\nData: 📌 (position), 🔴(record), 🆔 (ID), 𝑃 (FlowFields)\nFunctions: 🚄 (velocity), ∫ (integration), 🔧(postprocessing)\nNamedTuples: 𝐷 (diagnostics), 𝑀 (metadata)\n\nThe velocity function 🚄 typically computes velocity at individual positions (📌 to start) within the specified space-time domain by interpolating gridded variables (provided via 𝑃). Individual trajectories are computed by integrating (∫) interpolated velocities through time. Normally, integration is done by calling ∫! which updates 📌 at the end and records results in 🔴 via 🔧. Unicode cheatsheet:\n\n📌=\\:pushpin:<tab>, 🔴=\\:red_circle:<tab>, 🆔=\\:id:<tab>\n🚄=\\:bullettrain_side:<tab>, ∫=\\int<tab>, 🔧=\\:wrench:<tab>\n𝑃=\\itP<tab>, 𝐷=\\itD<tab>, 𝑀=\\itM<tab>\n\nSimple constructors that use FlowFields to choose adequate defaults:\n\nIndividuals(𝐹::𝐹_Array2D,x,y)\nIndividuals(𝐹::𝐹_Array3D,x,y,z)\nIndividuals(𝐹::𝐹_MeshArray2D,x,y,fid)\nIndividuals(𝐹::𝐹_MeshArray3D,x,y,z,fid)\n\nFurther customization is achievable via keyword constructors:\n\ndf=DataFrame( ID=[], x=[], y=[], z=[], t = [])\n𝐼=Individuals{Float64,2}(📌=zeros(3,10),🆔=1:10,🔴=deepcopy(df))\n𝐼=Individuals(📌=zeros(3,2),🆔=collect(1:2),🔴=deepcopy(df))\n\nOr via the plain text (or no-unicode) constructors:\n\ndf=DataFrame( ID=[], x=[], y=[], z=[], t = [])\nI=(position=zeros(3,2),ID=1:2,record=deepcopy(df))\nI=Individuals(I)\n\n\n\n\n\n","category":"type"},{"location":"workflow/#Main-Functions","page":"User Guide","title":"Main Functions","text":"","category":"section"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"∫!(𝐼,𝑇) displaces individuals 𝐼 continuously over time period 𝑇 according to velocity function 🚄, temporal integration method ∫, and post-processor 🔧 (all embedded within 𝐼).","category":"page"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"∫!","category":"page"},{"location":"workflow/#IndividualDisplacements.∫!","page":"User Guide","title":"IndividualDisplacements.∫!","text":"∫!(𝐼::Individuals,𝑇::Tuple)\n\nDisplace simulated individuals continuously through space over time period 𝑇 starting from position 📌. \n\nThis is typically achieved by computing the cumulative integral of velocity experienced by each individual along its trajectory (∫ 🚄 dt).\nThe current default is solve(prob,Tsit5(),reltol=1e-8,abstol=1e-8) but all solver options from the OrdinaryDiffEq.jl package are available.\nAfter this, ∫! is also equipped to postprocess results recorded into 🔴 via the 🔧 workflow, and the last step in ∫! consists in updating 📌 to be ready for continuing in a subsequent call to ∫!.\n\n\n\n\n\n∫!(𝐼::Individuals)\n\nCall ∫!(𝐼::Individuals,𝐼.𝑃.𝑇)\n\n\n\n\n\n","category":"function"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"The velocity interpolation functions (🚄) carry out the central computation of this package – interpolating gridded flow fields to individual positions 📌. It is normally called via ∫! to integrate velocity 🚄 over a chosen time period. ","category":"page"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"Velocity interpolation for several array and grid types.\nPreprocessing and postprocessing methods.\nI/O routines to read (write) results from (to) file.","category":"page"},{"location":"workflow/","page":"User Guide","title":"User Guide","text":"and other functionalities provided in src/compute.jl and src/data_wrangling.jl are further documented in the Tool Box section. Ingestion of trajectory data which have been collected by the Ocean Drifting Buoy Program (movie) is also supported.","category":"page"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"EditURL = \"https://github.com/JuliaClimate/IndividualDisplacements.jl/blob/master/examples/basics/particle_cloud.jl\"","category":"page"},{"location":"basics/particle_cloud/#Particle-Cloud","page":"Particle Cloud","title":"Particle Cloud","text":"","category":"section"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"(Image: ) (Image: )","category":"page"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"Using the same setup as detailed_look.jl or example2(), here we simulate a point cloud getting advected by the flow field. For additional documentation e.g. see : 1, 2, 3, 4","category":"page"},{"location":"basics/particle_cloud/#.-Import-Software","page":"Particle Cloud","title":"1. Import Software","text":"","category":"section"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"using IndividualDisplacements, OrdinaryDiffEq, Statistics\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/recipes_plots.jl\"))\ninclude(joinpath(p,\"../examples/example123.jl\"));\nnothing #hide","category":"page"},{"location":"basics/particle_cloud/#.-Setup-Problem","page":"Particle Cloud","title":"2. Setup Problem","text":"","category":"section"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"𝑃,Γ=example2_setup()\n\nii1=5:5:40; ii2=5:5:25\nx=vec([x-0.5 for x in ii1, y in ii2])\ny=vec([y-0.5 for x in ii1, y in ii2])\nxy = permutedims([[x[i];y[i];1.0] for i in eachindex(x)])\n\nsolv(prob) = solve(prob,Tsit5(),reltol=1e-6,abstol=1e-6)\ntr = DataFrame(ID=Int[], x=Float64[], y=Float64[], t=Float64[])\n\n#𝐼 = Individuals{Float64,2}(📌=xy[:,:], 🔴=tr, 🆔=collect(1:size(xy,2)),","category":"page"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":" 🚄 = dxdt!, ∫ = solv, 🔧 = postprocess_xy, 𝑃=𝑃);","category":"page"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"I=(position=xy,record=deepcopy(tr),velocity=dxdt!,\n integration=solv,postprocessing=postprocess_xy,parameters=𝑃)\n𝐼=Individuals(I)","category":"page"},{"location":"basics/particle_cloud/#.-Compute-Trajectories","page":"Particle Cloud","title":"3. Compute Trajectories","text":"","category":"section"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"𝑇 = (0.0,2998*3600.0)\n∫!(𝐼,𝑇)","category":"page"},{"location":"basics/particle_cloud/#.-Display-results","page":"Particle Cloud","title":"4. Display results","text":"","category":"section"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"𝐼.🔴.lon=5000*𝐼.🔴.x\n𝐼.🔴.lat=5000*𝐼.🔴.y\nplt=plot_paths(𝐼.🔴,size(xy,2),100000.0)","category":"page"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"Compare with trajectory output from MITgcm","category":"page"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"#df=read_flt(IndividualDisplacements.flt_example,Float32)\n#ref=plot_paths(df,size(xy,2),100000.0)","category":"page"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"","category":"page"},{"location":"basics/particle_cloud/","page":"Particle Cloud","title":"Particle Cloud","text":"This page was generated using Literate.jl.","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"EditURL = \"https://github.com/JuliaClimate/IndividualDisplacements.jl/blob/master/examples/basics/random_flow_field.jl\"","category":"page"},{"location":"basics/random_flow_field/#Two-Dimensions","page":"Two Dimensions","title":"Two Dimensions","text":"","category":"section"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"(Image: ) (Image: )","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"Simulate trajectories of a particle cloud in a two-dimensional flow field. A doubly-periodic domain and simple flow fields are used. For additional documentation e.g. see : 1, 2, 3, 4","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"Exercises:","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"change the initial distribution of particles\nincrease the duration of the trajectories simulation\ntreat the non-periodic domain case by padding u,v with zeros\nreplace u,v with your own two-dimensional flow fields","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"(Image: particles in random flow)","category":"page"},{"location":"basics/random_flow_field/#.-Import-Software","page":"Two Dimensions","title":"1. Import Software","text":"","category":"section"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"using IndividualDisplacements, DataFrames\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/flow_fields.jl\"));\nnothing #hide","category":"page"},{"location":"basics/random_flow_field/#.-Flow-Fields","page":"Two Dimensions","title":"2. Flow Fields","text":"","category":"section"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"Let's start with a simple, doubly periodic flow field defined by a streamfunction and create the FlowFields data structure which will then be drive the individual displacement and trajectory computations","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"nx=16\ndx= π/nx\nXC = dx*(collect(1:2*nx) .- 0.5)\nYC = dx*(collect(1:nx) .- 0.5)\n\nfac=0.1\nf(x, y) = sin(x) + cos(y) #streamfunction\nϕ = fac*[f(x, y) for x in XC,y in YC] #streamfunction\nuC = -fac*[sin(y) for x in XC,y in YC] #dphi/dy at cell center\nvC = -fac*[cos(x) for x in XC,y in YC]; #-dphi/dx at cell center\nnothing #hide","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"When starting as done here with collocated velocities in m/s units (uC,vC at the grid cell center), one easily obtains the normalized, staggered C-grid velocities (u,v) as shown below. u (resp v) is staggered by -0.5 grid point in direction 1 for u (2 for v) from the grid cell center uC,vC. This staggering of variables as well as the normalization of velocities by the grid scale are key conventions adopted in IndividualDisplacements.jl.","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"u=0.5*(circshift(uC, (1,0))+uC) /dx #staggered u converted to grid point units (m/s -> 1/s)\nv=0.5*(circshift(vC, (0,1))+vC) /dx #staggered v converted to grid point units (m/s -> 1/s)\n\n𝐹=FlowFields(u,u,v,v,[0.,10.])","category":"page"},{"location":"basics/random_flow_field/#.-Initialize-Individuals","page":"Two Dimensions","title":"3. Initialize Individuals","text":"","category":"section"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"For example, we can initialize 100 particles within a central subdomain as follows.","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"np,nq=size(u)\nx=np*(0.4 .+ 0.2*rand(100))\ny=nq*(0.4 .+ 0.2*rand(100));\nnothing #hide","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"The following constructor function wraps everything in the Individuals data structure.","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"𝐼=Individuals(𝐹,x,y)","category":"page"},{"location":"basics/random_flow_field/#.-Compute-Trajectories","page":"Two Dimensions","title":"4. Compute Trajectories","text":"","category":"section"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"The time period is 𝐼.𝑃.𝑇 by default, unless ∫!(𝐼,𝑇) is called instead.","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"∫!(𝐼)","category":"page"},{"location":"basics/random_flow_field/#.-Plot-Results","page":"Two Dimensions","title":"5. Plot Results","text":"","category":"section"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"p=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/recipes_plots.jl\"));\n\n🔴_by_t = groupby(𝐼.🔴, :t)\nphi_scatter(ϕ,🔴_by_t[end])","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"Or to generate a simple animation:","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"anim = @animate for t in eachindex(🔴_by_t)\n phi_scatter(ϕ,🔴_by_t[t])\nend\n\npth=tempdir()*\"/\"\ngif(anim, pth*\"RandomFlow.gif\", fps = 10)","category":"page"},{"location":"basics/random_flow_field/#.-Alternatives-(optional)","page":"Two Dimensions","title":"6. Alternatives (optional)","text":"","category":"section"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"Making the flow field time variable simply involves providing two different flow fields. Linear interpolation will then be applied in the specified time range. For example :","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"𝐹=FlowFields(-u,u,-v,v,[0.,10.])","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"It is often convenient to set up FlowFields using the MeshArrays.jl package, which handles such staggered grids in general fashion, instead of plain Arrays. Given a doubly periodic flow field defined as before this is readily done via the convert_to_FlowFields function.","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"u,v,ϕ=random_flow_field()\n#𝐹=FlowFields(u,u,v,v,[0.,10.])\n𝐹=convert_to_FlowFields(u,v,10.0);","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"We should note that u,v derive from streamfunction ϕ which is defined at the corner point in random_flow_field. Doing this ensures that the resulting u,v is non-divergent / purely-rotational over the C-grid domain. In brief:","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"u=-(circshift(ϕ, (0,-1))-ϕ)\nv=(circshift(ϕ, (-1,0))-ϕ)","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"In contrast uC, vC computed as earlier in this example may contain contain both rotational and divergent components – if this were an important consideration, MeshArrays.jl provides tools that can be used to e.g. ensure non-divergence.","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"When using MeshArray flow fields instead of plain Array flow fields, initial positions also include a subdomain array index (a; all ones in our example).","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"a=ones(size(x))\n#isa(𝐹,𝐹_MeshArray2D)\n𝐼=Individuals(𝐹,x,y,a)","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"","category":"page"},{"location":"basics/random_flow_field/","page":"Two Dimensions","title":"Two Dimensions","text":"This page was generated using Literate.jl.","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"EditURL = \"https://github.com/JuliaClimate/IndividualDisplacements.jl/blob/master/examples/basics/detailed_look.jl\"","category":"page"},{"location":"basics/detailed_look/#Detailed-Look","page":"Detailed Look","title":"Detailed Look","text":"","category":"section"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"(Image: ) (Image: )","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"A more detailed look at spatial interpolation, integration through time, and I/O. For additional documentation e.g. see 1, 2, 3, 4. Here we illustrate a few things in more detail:","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"reading velocities from file.\ngridded velocity output (Udata, Vdata)\npre-computed trajectory output (float_traj*data)\ninterpolating U,V from gridded output to individual locations\ncompared with u,v from float_traj*data\ncomputing trajectories (location v time) using OrdinaryDiffEq.jl\ncompared with x(t),y(t) from float_traj*data","category":"page"},{"location":"basics/detailed_look/#.-Import-Software","page":"Detailed Look","title":"1. Import Software","text":"","category":"section"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"using IndividualDisplacements, OrdinaryDiffEq, DataFrames, MITgcmTools\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/recipes_plots.jl\"))\ninclude(joinpath(p,\"../examples/example123.jl\"))\ninclude(joinpath(p,\"../examples/helper_functions.jl\"));\nnothing #hide","category":"page"},{"location":"basics/detailed_look/#.-Read-Trajectory-Output","page":"Detailed Look","title":"2. Read Trajectory Output","text":"","category":"section"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"from MITgcm/pkg/flt","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"dirIn=IndividualDisplacements.flt_example\nprec=Float32\ndf=read_flt(dirIn,prec);\n\nplt=plot_paths(df,300,100000.0)","category":"page"},{"location":"basics/detailed_look/#.-Read-Gridded-Variables","page":"Detailed Look","title":"3. Read Gridded Variables","text":"","category":"section"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"using MeshArrays.jl and e.g. a NamedTyple","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"𝑃,Γ=example2_setup();\nnothing #hide","category":"page"},{"location":"basics/detailed_look/#.-Visualize-Velocity-Fields","page":"Detailed Look","title":"4. Visualize Velocity Fields","text":"","category":"section"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"plt=heatmap(Γ.mskW[1,1].*𝑃.u0,title=\"U at the start\")\nplt=heatmap(Γ.mskW[1,1].*𝑃.u1-𝑃.u0,title=\"U end - U start\")","category":"page"},{"location":"basics/detailed_look/#.-Visualize-Trajectories","page":"Detailed Look","title":"5. Visualize Trajectories","text":"","category":"section"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"(select one trajectory)","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"tmp=df[df.ID .== 200, :]\ntmp[1:4,:]","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"Super-impose trajectory over velocity field (first for u ...)","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"x=Γ.XG.f[1][:,1]\ny=Γ.YC.f[1][1,:]\nz=transpose(Γ.mskW[1].*𝑃.u0);\nnothing #hide","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"plt=contourf(x,y,z,c=:delta) plot!(tmp[:,:lon],tmp[:,:lat],c=:red,w=4,leg=false)","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"Super-impose trajectory over velocity field (... then for v)","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"x=Γ.XC.f[1][:,1]\ny=Γ.YG.f[1][1,:]\nz=transpose(Γ.mskW[1].*𝑃.v0);\nnothing #hide","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"plt=contourf(x,y,z,c=:delta) plot!(tmp[:,:lon],tmp[:,:lat],c=:red,w=4,leg=false)","category":"page"},{"location":"basics/detailed_look/#.-Interpolate-Velocities","page":"Detailed Look","title":"6. Interpolate Velocities","text":"","category":"section"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"dx=Γ.dx\nuInit=[tmp[1,:lon];tmp[1,:lat]]./dx\nnSteps=Int32(tmp[end,:time]/3600)-2\ndu=fill(0.0,2);\nnothing #hide","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"Visualize and compare with actual grid point values – jumps on the tangential component are expected with linear scheme:","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"tmpu=fill(0.0,100)\ntmpv=fill(0.0,100)\ntmpx=fill(0.0,100)\nfor i=1:100\n tmpx[i]=500.0 *i./dx\n dxdt!(du,[tmpx[i];0.499./dx],𝑃,0.0)\n tmpu[i]=du[1]\n tmpv[i]=du[2]\nend\n\nplt=plot(tmpx,tmpu,label=\"u (interp)\")\nplot!(Γ.XG.f[1][1:10,1]./dx,𝑃.u0[1:10,1],marker=:o,label=\"u (C-grid)\")\nplot!(tmpx,tmpv,label=\"v (interp)\")\nplot!(Γ.XG.f[1][1:10,1]./dx,𝑃.v0[1:10,1],marker=:o,label=\"v (C-grid)\")","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"And similarly in the other direction","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"tmpu=fill(0.0,100)\ntmpv=fill(0.0,100)\ntmpy=fill(0.0,100)\nfor i=1:100\n tmpy[i]=500.0 *i./dx\n dxdt!(du,[0.499./dx;tmpy[i]],𝑃,0.0)\n tmpu[i]=du[1]\n tmpv[i]=du[2]\nend","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"plt=plot(tmpx,tmpu,label=\"u (interp)\") plot!(Γ.YG.f[1][1,1:10]./dx,𝑃.u0[1,1:10],marker=:o,label=\"u (C-grid)\") plot!(tmpx,tmpv,label=\"v (interp)\") plot!(Γ.YG.f[1][1,1:10]./dx,𝑃.v0[1,1:10],marker=:o,label=\"v (C-grid)\")","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"Compare recomputed velocities with those from pkg/flt","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"nSteps=2998\ntmpu=fill(0.0,nSteps); tmpv=fill(0.0,nSteps);\ntmpx=fill(0.0,nSteps); tmpy=fill(0.0,nSteps);\nrefu=fill(0.0,nSteps); refv=fill(0.0,nSteps);\nfor i=1:nSteps\n dxy_dt_replay(du,[tmp[i,:lon],tmp[i,:lat]],tmp,tmp[i,:time])\n refu[i]=du[1]./dx\n refv[i]=du[2]./dx\n dxdt!(du,[tmp[i,:lon],tmp[i,:lat]]./dx,𝑃,Float64(tmp[i,:time]))\n tmpu[i]=du[1]\n tmpv[i]=du[2]\nend","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"plt=plot(tmpu,label=\"u\") plot!(tmpv,label=\"v\") plot!(refu,label=\"u (ref)\") plot!(refv,label=\"v (ref)\")","category":"page"},{"location":"basics/detailed_look/#.-Compute-Trajectories","page":"Detailed Look","title":"6. Compute Trajectories","text":"","category":"section"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"Solve through time using OrdinaryDiffEq.jl with","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"dxdt! is the function computing d(position)/dt\nuInit is the initial condition u @ tspan[1]\ntspan is the time interval\n𝑃 are parameters for dxdt!\nTsit5 is the time-stepping scheme\nreltol and abstol are tolerance parameters","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"tspan = (0.0,nSteps*3600.0)\n#prob = ODEProblem(dxy_dt_replay,uInit,tspan,tmp)\nprob = ODEProblem(dxdt!,uInit,tspan,𝑃)\nsol = solve(prob,Tsit5(),reltol=1e-8,abstol=1e-8)\nsol[1:4]","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"Compare recomputed trajectories with originals from MITgcm/pkg/flt","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"ref=transpose([tmp[1:nSteps,:lon] tmp[1:nSteps,:lat]])\nmaxLon=80*5.e3\nmaxLat=42*5.e3\n#show(size(ref))\nfor i=1:nSteps-1\n ref[1,i+1]-ref[1,i]>maxLon/2 ? ref[1,i+1:end]-=fill(maxLon,(nSteps-i)) : nothing\n ref[1,i+1]-ref[1,i]<-maxLon/2 ? ref[1,i+1:end]+=fill(maxLon,(nSteps-i)) : nothing\n ref[2,i+1]-ref[2,i]>maxLat/2 ? ref[2,i+1:end]-=fill(maxLat,(nSteps-i)) : nothing\n ref[2,i+1]-ref[2,i]<-maxLat/2 ? ref[2,i+1:end]+=fill(maxLat,(nSteps-i)) : nothing\nend\nref=ref./dx;\n\nplt=plot(sol[1,:],sol[2,:],linewidth=5,title=\"Using Recomputed Velocities\",\n xaxis=\"lon\",yaxis=\"lat\",label=\"Julia Solution\") # legend=false\nplot!(ref[1,:],ref[2,:],lw=3,ls=:dash,label=\"MITgcm Solution\")","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"","category":"page"},{"location":"basics/detailed_look/","page":"Detailed Look","title":"Detailed Look","text":"This page was generated using Literate.jl.","category":"page"},{"location":"#IndividualDisplacements.jl","page":"Introduction","title":"IndividualDisplacements.jl","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"IndividualDisplacements.jl computes elementary point displacements over a gridded Earth domain (e.g. a climate model C-grid). A typical application is the simulation and analysis of materials moving through atmospheric flows (e.g. dust or chemicals) or oceanic flows (e.g. plastics or planktons).","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"Inter-operability with common climate model grids and their representation in MeshArrays.jl is a central element (docs). IndividualDisplacements.jl can also read and plot trajectories using MIT General Circulation Model output or Ocean Drifting Buoy data (movie). It was originally developed using ECCOv4 and CBIOMES ocean model simulations (Forget et al. 2015, Forget, 2018).","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"(Image: simulated particle movie (95m))","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"(Image: Global Drifter Program data)","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"EditURL = \"https://github.com/JuliaClimate/IndividualDisplacements.jl/blob/master/examples/worldwide/three_dimensional_ocean.jl\"","category":"page"},{"location":"worldwide/three_dimensional_ocean/#Three-Dimensions","page":"Three Dimensions","title":"Three Dimensions","text":"","category":"section"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"(Image: ) (Image: )","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"Advect particles with climatological mean flow in three dimensions starting from a selected depth level (e.g. k=10 for 95 m) and region using a near-global ocean state estimate (OCCA which is here repeated for two years. For additional documentation e.g. see : 1, 2, 3, 4","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"(Image: Three dimensional simulation)","category":"page"},{"location":"worldwide/three_dimensional_ocean/#.-Load-Software","page":"Three Dimensions","title":"1. Load Software","text":"","category":"section"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"using IndividualDisplacements, DataFrames\n\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/helper_functions.jl\"))\nIndividualDisplacements.get_occa_velocity_if_needed();\nnothing #hide","category":"page"},{"location":"worldwide/three_dimensional_ocean/#.1-Ocean-Circulation-Setup","page":"Three Dimensions","title":"2.1 Ocean Circulation Setup","text":"","category":"section"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"𝑃,𝐷,Γ=OCCA_FlowFields(nmax=5);\nnothing #hide","category":"page"},{"location":"worldwide/three_dimensional_ocean/#.3-Initialize-Individual-Positions","page":"Three Dimensions","title":"2.3 Initialize Individual Positions","text":"","category":"section"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"\"\"\"\n initial_positions(Γ; nf=10000, lon_rng=(-160.0,-159.0), lat_rng=(30.0,31.0))\n\nRandomly assign initial positions in longitude,latitude ranges. Positions are\nexpressed in, normalized, grid point units (x,y in the 0,nx and 0,ny range).\nTo convert from longitude,latitude here we take advantage of the regularity\nof the 1 degree grid being used -- for a more general alternative, see the\nglobal ocean example.\n\"\"\"\nfunction initial_positions(Γ::NamedTuple, nf=10000, lon_rng=(-160.0,-159.0), lat_rng=(30.0,31.0))\n lon=lon_rng[1] .+(lon_rng[2]-lon_rng[1]).*rand(nf)\n lat=lat_rng[1] .+(lat_rng[2]-lat_rng[1]).*rand(nf)\n x=lon .+ (21. - Γ.XC[1][21,1])\n y=lat .+ (111. - Γ.YC[1][1,111])\n return x,y\nend","category":"page"},{"location":"worldwide/three_dimensional_ocean/#.3-Diagnostic-/-Post-Processing-Setup","page":"Three Dimensions","title":"2.3 Diagnostic / Post-Processing Setup","text":"","category":"section"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"custom🔴 = DataFrame(ID=Int[], fid=Int[], x=Float64[], y=Float64[],\n k=Float64[], z=Float64[], iso=Float64[], t=Float64[],\n lon=Float64[], lat=Float64[], year=Float64[], col=Symbol[])\n\nfunction custom🔧(sol,𝑃::𝐹_MeshArray3D;id=missing,𝑇=missing)\n df=postprocess_MeshArray(sol,𝑃,id=id,𝑇=𝑇)\n add_lonlat!(df,𝐷.XC,𝐷.YC)\n\n #add year (convenience time axis for plotting)\n df.year=df.t ./86400/365\n\n #add depth (i.e. the 3rd, vertical, coordinate)\n k=[sol[1,i,j][3] for i in 1:size(sol,2), j in 1:size(sol,3)]\n nz=length(𝐼.𝑃.u1)\n df.k=min.(max.(k[:],Ref(0.0)),Ref(nz)) #level\n k=Int.(floor.(df.k)); w=(df.k-k);\n df.z=𝐷.RF[1 .+ k].*(1 .- w)+𝐷.RF[2 .+ k].*w #depth\n\n #add one isotherm depth\n θ=0.5*(𝐷.θ0+𝐷.θ1)\n d=isosurface(θ,15,𝐷.RC)\n d[findall(isnan.(d))].=0.\n df.iso=interp_to_xy(df,exchange(d));\n\n #add color = f(iso-z)\n c=fill(:gold,length(df.iso))\n c[findall(df.iso.<df.z)].=:violet\n df.col=c\n\n #to plot e.g. Pacific Ocean transports, shift longitude convention?\n df.lon[findall(df.lon .< 0.0 )] = df.lon[findall(df.lon .< 0.0 )] .+360.0\n return df\nend","category":"page"},{"location":"worldwide/three_dimensional_ocean/#.4-Individuals-Data-Structure","page":"Three Dimensions","title":"2.4 Individuals Data Structure","text":"","category":"section"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"Set up Individuals data structure with nf particles moving in 3D on a regular 1 degree resolution grid covering most of the Globe.","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"nf=100; lo=(-160.0,-150.0); la=(30.0,40.0); kk=2.5;\ndf=DataFrame(:z => fill(kk,nf),:f => fill(1,nf))\n(df.x,df.y)=initial_positions(Γ, nf, lo, la)\n\n𝐼=Individuals(𝑃,df.x,df.y,df.z,df.f,(🔴=custom🔴,🔧=custom🔧))","category":"page"},{"location":"worldwide/three_dimensional_ocean/#.1-Compute-Displacements","page":"Three Dimensions","title":"3.1 Compute Displacements","text":"","category":"section"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"𝑇=(0.0,10*86400.0)\n\n∫!(𝐼,𝑇)","category":"page"},{"location":"worldwide/three_dimensional_ocean/#.2-Analyze-Results","page":"Three Dimensions","title":"3.2 Analyze Results","text":"","category":"section"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"The recorded simulation output, 🔴, is a in the DataFrames tabular format, which is easily manipulated or plotted.","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"either Plots.jl:","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"include(joinpath(p,\"../examples/recipes_plots.jl\"))\np=plot(𝐼)\n#p=map(𝐼,OceanDepthLog(Γ))\ndisplay(p)","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"or Makie.jl:","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"include(joinpath(p,\"../examples/recipes_Makie.jl\"))\n#p=plot(𝐼)\np=plot_paths(𝐼.🔴,100,180.);\ndisplay(p)","category":"page"},{"location":"worldwide/three_dimensional_ocean/#.3-Alternatives-(optional-/-unit-testing)","page":"Three Dimensions","title":"3.3 Alternatives (optional / unit testing)","text":"","category":"section"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"(x,y,z,f)=𝐼.📌[1]\n𝐽=Individuals(𝐼.𝑃,x,y,z,f)\ndiff(𝐼)\ngcdist(𝐼);\nnothing #hide","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"","category":"page"},{"location":"worldwide/three_dimensional_ocean/","page":"Three Dimensions","title":"Three Dimensions","text":"This page was generated using Literate.jl.","category":"page"},{"location":"API/#Velocity-Interpolation","page":"Tool Box","title":"Velocity Interpolation","text":"","category":"section"},{"location":"API/","page":"Tool Box","title":"Tool Box","text":"The dxdt! etc functions compute the tracked individual velocity. ","category":"page"},{"location":"API/","page":"Tool Box","title":"Tool Box","text":"dxdt!\ndxy_dt_replay\ndxy_dt_CyclicArray","category":"page"},{"location":"API/#IndividualDisplacements.dxdt!","page":"Tool Box","title":"IndividualDisplacements.dxdt!","text":"dxdt!(du,u,p::𝐹_MeshArray3D,tim)\n\nInterpolate velocity from gridded fields (3D; with halos) to position u (x,y,z,fIndex) to compute the derivative of position v time du_dt.\n\nusing IndividualDisplacements, Statistics\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/worldwide/three_dimensional_ocean.jl\"))\nref=[211. 34. -70.]\nprod(isapprox.([mean(𝐼.🔴.lon) mean(𝐼.🔴.lat) mean(𝐼.🔴.z)],ref,atol=50.0))\n\n# output\n\ntrue\n\n\n\n\n\ndxdt!(du,u,p::𝐹_MeshArray2D,tim)\n\nInterpolate velocity from gridded fields (2D; with halos) to position u (x,y,fIndex) to compute the derivative of position v time du_dt.\n\nusing IndividualDisplacements, Statistics\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/flow_fields.jl\"));\n\nu,v,ϕ=random_flow_field()\n#𝐹=𝐹_Array2D(u,u,v,v,[0.,10.])\n𝐹=convert_to_FlowFields(u,v,10.0)\n\nnp,nq=size(u)\nx=np*(0.4 .+ 0.2*rand(100))\ny=nq*(0.4 .+ 0.2*rand(100))\n\na=ones(size(x))\n𝐼=Individuals(𝐹,x,y,a)\n∫!(𝐼)\n\nref=size(u) ./2\nprod(isapprox.([mean(𝐼.🔴.x) mean(𝐼.🔴.y)],ref,atol=10.0))\n\n# output\n\ntrue\n\nusing IndividualDisplacements, Statistics\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/worldwide/global_ocean_circulation.jl\"))\nref=[78. 88.]\nprod(isapprox.([mean(𝐼.🔴.x) mean(𝐼.🔴.y)],ref,atol=10.0))\n\n# output\n\ntrue\n\n\n\n\n\ndxdt!(du,u,𝑃::𝐹_Array3D,tim)\n\nInterpolate velocity from gridded fields (3D; NO halos) to position u (x,y,z) to compute the derivative of position v time du_dt.\n\nusing IndividualDisplacements\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/basics/solid_body_rotation.jl\"))\nref=[7.767441577479032 9.513402495574852 0.7065855989421701]\nprod(isapprox.(𝐼.📌',ref,atol=1.0))\n\n# output\n\ntrue\n\n\n\n\n\ndxdt!(du,u,𝑃::𝐹_Array2D,tim)\n\nInterpolate velocity from gridded fields (2D; NO halos) to position u (x,y) to compute the derivative of position v time du_dt.\n\nusing IndividualDisplacements, Statistics\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/basics/particle_cloud.jl\"))\nref=[29.381183342468674 19.890831699436823]\nprod(isapprox.([mean(𝐼.🔴.x) mean(𝐼.🔴.y)],ref,atol=1.0))\n\n# output\n\ntrue\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.dxy_dt_replay","page":"Tool Box","title":"IndividualDisplacements.dxy_dt_replay","text":"dxy_dt_replay(du,u,p::DataFrame,t)\n\nInterpolate velocity from MITgcm float_trajectories output and return position increment du.\n\nusing IndividualDisplacements, Statistics\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/basics/detailed_look.jl\"))\nprod(isapprox.(sol[:,end],ref[:,end],atol=1.0))\n\n# output\n\ntrue\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.dxy_dt_CyclicArray","page":"Tool Box","title":"IndividualDisplacements.dxy_dt_CyclicArray","text":"dxy_dt_CyclicArray(du,u,𝑃::NamedTuple,tim)\n\nNearest neighbor (?) velocity from gridded fields (2D; NO halos but not needed when CyclicArrays is used to extend valid indice ranges).\n\nnotes: spatial interpolation & temporal interpolation are lacking\n\nusing IndividualDisplacements, Statistics\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/example_CyclicArray.jl\"))\n(x,y)=cyclicarray_example()\nref=[270. 243.]\nprod(isapprox.([mean(x) mean(y)],ref,atol=1.0))\n\n# output\n\ntrue\n\n\n\n\n\n","category":"function"},{"location":"API/#Setup-And-Postprocessing","page":"Tool Box","title":"Setup And Postprocessing","text":"","category":"section"},{"location":"API/","page":"Tool Box","title":"Tool Box","text":"Convenience functions to initialize a simulation and post-process the output are provided. ","category":"page"},{"location":"API/","page":"Tool Box","title":"Tool Box","text":"postprocess_xy\npostprocess_MeshArray\nrandn_lonlat\ninterp_to_lonlat\ninterp_to_xy\nnearest_to_xy\ngcdist","category":"page"},{"location":"API/#IndividualDisplacements.postprocess_xy","page":"Tool Box","title":"IndividualDisplacements.postprocess_xy","text":"postprocess_xy()\n\nCopy sol to a DataFrame & map position to x,y coordinates, and define time axis for a simple doubly periodic domain\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.postprocess_MeshArray","page":"Tool Box","title":"IndividualDisplacements.postprocess_MeshArray","text":"postprocess_MeshArray(sol,𝑃::FlowFields; id=missing, 𝑇=missing)\n\nCopy sol to a DataFrame & map position to lon,lat coordinates using \"exchanged\" 𝐷.XC, 𝐷.YC via add_lonlat!\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.randn_lonlat","page":"Tool Box","title":"IndividualDisplacements.randn_lonlat","text":"randn_lonlat(nn=1,seed=missing)\n\nRandomly distributed longitude, latitude positions on the sphere.\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.interp_to_lonlat","page":"Tool Box","title":"IndividualDisplacements.interp_to_lonlat","text":"interp_to_lonlat\n\nUse MeshArrays.Interpolate() to interpolate to e.g. a regular grid (e.g. maps for plotting purposes).\n\nusing IndividualDisplacements\np=dirname(pathof(IndividualDisplacements))\ninclude(joinpath(p,\"../examples/helper_functions.jl\"))\n𝑃,𝐷=global_ocean_circulation(k=1,ny=2);\n\nlon=[i for i=20.:20.0:380., j=-70.:10.0:70.]\nlat=[j for i=20.:20.0:380., j=-70.:10.0:70.]\n(f,i,j,w,_,_,_)=InterpolationFactors(𝐷.Γ,vec(lon),vec(lat))\nIntFac=(lon=lon,lat=lat,f=f,i=i,j=j,w=w)\n\ntmp1=interp_to_lonlat(𝐷.Γ.Depth,𝐷.Γ,lon,lat)\ntmp2=interp_to_lonlat(𝐷.Γ.Depth,IntFac)\n\nref=[5896. 5896.]\nprod(isapprox.([maximum(tmp1) maximum(tmp2)],ref,atol=1.0))\n\n# output\n\ntrue\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.interp_to_xy","page":"Tool Box","title":"IndividualDisplacements.interp_to_xy","text":"interp_to_xy(df::DataFrame,Zin::MeshArray)\n\nInterpolate \"exchanged\" / \"hallo-included\" Zin to df[!,:x], df[!,:y] on df[!,:fid]\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.nearest_to_xy","page":"Tool Box","title":"IndividualDisplacements.nearest_to_xy","text":"nearest_to_xy(α::MeshArray,x,y,f)\n\nValue of α at eachindex of the grid cell center nearest to x,y on subdomain array / facet f\n\n\n\n\n\nnearest_to_xy(α::Array,x,y)\n\nValue of α at eachindex of the grid cell center nearest to x,y\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.gcdist","page":"Tool Box","title":"IndividualDisplacements.gcdist","text":"gcdist(𝐼::Individuals)\n\nGreat circle distance (gcd in radians) between final and initial positions.\n\n\n\n\n\n","category":"function"},{"location":"API/#Read-Output-From-File","page":"Tool Box","title":"Read Output From File","text":"","category":"section"},{"location":"API/","page":"Tool Box","title":"Tool Box","text":"Trajectory simulated by the MITgcm or observed by the global drifter program can be read from file using, respectively MITgcmTools.read_flt or read_drifters.","category":"page"},{"location":"API/","page":"Tool Box","title":"Tool Box","text":"read_drifters\nread_velocities\nread_mds","category":"page"},{"location":"API/#IndividualDisplacements.read_drifters","page":"Tool Box","title":"IndividualDisplacements.read_drifters","text":"read_drifters(pth,lst;chnk=Inf,rng=(missing,missing))\n\nRead near-surface drifter data from the Global Drifter Program into a DataFrame.\n\nNote: need to use NetCDF.jl as NCDatasets.jl errors when TIME = Inf\n\npth,list=drifter_files()\ndf=read_drifters( pth*lst[end],chnk=1000,rng=(2014.1,2014.2) )\n#sort!(df, [:t, :lat])\n#CSV.write(pth*\"Drifter_hourly_2005_2019.csv\", df)\n\n\n\n\n\nread_drifters( pth, lst )\n\nRead near-surface hourly drifter data from the Global Drifter Program into a DataFrame.\n\nNote: need to use NetCDF.jl as NCDatasets.jl errors when TIME = Inf\n\npth,list=drifter_files()\ndf=read_drifters( pth, lst)\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.read_velocities","page":"Tool Box","title":"IndividualDisplacements.read_velocities","text":"read_velocities(γ::gcmgrid,t::Int,pth::String)\n\nRead velocity components u,v from files in pthfor time t\n\n\n\n\n\n","category":"function"},{"location":"API/#IndividualDisplacements.read_mds","page":"Tool Box","title":"IndividualDisplacements.read_mds","text":"read_mds(filRoot::String,x::MeshArray)\n\nRead a gridded variable from 2x2 tile files. This is used in example2_setup() with flt_example/\n\n\n\n\n\n","category":"function"}]
}