Reference
Constants
Muscade.noFB — ConstantnoFBA constant, used by elements' residual or lagrangian as their 3rd output if they do provide any feedback to the solver (for example, on the reduction of the barrier parameter in interior point method).
Example: return L,noFB
See also: noFB
Muscade.ϵ — Constantϵ (\epsilon)an alias for Base.eps(𝕣).
Muscade.∞ — Constant∞ (\infty)an alias for Base.inf.
Types
Muscade.AbstractElement — TypeAbstractElementAn abstract data type. An element type MyElement must be declared as a subtype of AbstractElement.
MyELementmust provide a constructor with interface
`eleobj = MyElement(nod::Vector{Node}; kwargs...)`See also: coord, Node, lagrangian
Muscade.DirectXUA — TypeDirectXUA{OX,OU,IA}A non-linear direct solver for optimisation FEM.
An analysis is carried out by a call with the following syntax:
initialstate = initialize!(model)
stateXUA = solve(DirectXUA{OX,OU,IA};initialstate,time=0:1.:5)The solver does not yet support interior point methods.
Parameters
OX0 for static analysis 1 for first order problems in time (viscosity, friction, measurement of velocity) 2 for second order problems in time (inertia, measurement of acceleration)OU0 for white noise prior to the unknown load process 2 otherwiseIA0 for XU problems (variables of class A will be unchanged) 1 for XUA problems
Named arguments
dbg=(;)a named tuple to trace the call tree (for debugging).verbose=trueset to false to suppress printed output (for testing).silenterror=falseset to true to suppress print out of error (for testing) .initialstateaState.timeanAbstractRangeof times at which to compute the steps. Example: 0:0.1:5.maxiter=50maximum number of Newton-Raphson iterations.maxΔλ=1e-5convergence criteria: a norm of the scaledΛincrement.maxΔx=1e-5convergence criteria: a norm of the scaledXincrement.maxΔu=1e-5convergence criteria: a norm of the scaledUincrement.maxΔa=1e-5convergence criteria: a norm of the scaledAincrement.saveiter=falseset to true so that the outputstateis a vector (over the iterations) of vectors (over the steps) ofStates of the model (for debugging non-convergence).
Setting the following flags to true will improve the sparsity of the system. But setting a flag to true when the condition isn't met causes the Hessian to be wrong, which is detrimental for convergence.
Xwhite=falsetrueif response measurement error is a white noise process.XUindep=falsetrueif response measurement error is independant ofUUAindep=falsetrueifUis independant ofAXAindep=falsetrueif response measurement error is independant ofA
Output
A vector of length equal to that of time containing the state of the optimized model at each of these steps.
See also: solve, initialize!, SweepX, FreqXU
Muscade.DofConstraint — TypeDofConstraint{λclass,Nx,Nu,Na,xinod,xfield,uinod,ufield,ainod,
afield,λinod,λfield,Tg,Tmode} <: AbstractElementAn element to apply physical/optimisation equality/inequality constraints on dofs.
The constraints are holonomic, i.e. they apply to the values, not the time derivatives, of the involved dofs. This element is very general but not very user-friendly to construct, factory functions are provided for better useability. The sign convention is that the gap g≥0 and the Lagrange multiplier λ≥0.
This element can generate three classes of constraints, depending on the input argument λclass.
λclass=:XPhysical constraint. In mechanics, the Lagrange multiplier dof is a generalized force, dual of the gap. The gap function must be of the formgap(x,t,gargs...).λclass=:UTime varying optimisation constraint. For example: findA-parameters so that at all times, the response does not exceed a given criteria. The gap function must be of the formgap(x,u,a,t,gargs...).λclass=:ATime invariant optimisation constraint. For example: findA-parameters such thatA[1]+A[2]=gargs.somevalue. The gap function must be of the formgap(a,gargs...).
Named arguments to the constructor
xinod::NTuple{Nx,𝕫}=()For each X-dof to be constrained, its element-node number.xfield::NTuple{Nx,Symbol}=()For each X-dof to be constrained, its field.uinod::NTuple{Nu,𝕫}=()For each U-dof to be constrained, its element-node number.ufield::NTuple{Nu,Symbol}=()For each U-dof to be constrained, its field.ainod::NTuple{Na,𝕫}=()For each A-dof to be constrained, its element-node number.afield::NTuple{Na,Symbol}=()For each A-dof to be constrained, its field.λinod::𝕫The element-node number of the Lagrange multiplier.λclass::SymbolThe class (:X,:Uor:A) of the Lagrange multiplier. See the explanation above for classes of constraintsλfield::SymbolThe field of the Lagrange multiplier.gap::FunctionThe gap function.gargs::NTupleAdditional inputs to the gap function.mode::Functionwheremode(t::ℝ) -> Symbol, with value:equal,:positiveor:offat any time. An:offconstraint will set the Lagrange multiplier to zero.
Example
using Muscade
model = Model(:TestModel)
n1 = addnode!(model,𝕣[0])
e1 = addelement!(model,DofConstraint,[n1],xinod=(1,),xfield=(:t1,),
λinod=1, λclass=:X, λfield=:λ1,gap=(x,t)->x[1]+.1,
mode=positive)
e2 = addelement!(model,QuickFix ,[n1],inod=(1,),field=(:t1,),
res=(x,u,a,t)->0.4x.+.08+.5x.^2)
initialstate = initialize!(model)
setdof!(initialstate,1.;field=:λ1)
state = solve(SweepX{0};initialstate,time=[0.],verbose=false)
X = state[1].X[1]See also: Hold, ElementConstraint, off, equal, positive
Muscade.DofCost — TypeDofCost{Class,Nx,Nu,Na,xinod,xfield,uinod,ufield,ainod,
afield,Tcost,Tcostargs} <: AbstractElementAn element to apply costs on combinations of dofs.
Named arguments to the constructor
xinod::NTuple{Nx,𝕫}=()For each X-dof to entercost, its element-node number.xfield::NTuple{Nx,Symbol}=()For each X-dof to entercost, its field.uinod::NTuple{Nu,𝕫}=()For each U-dof to entercost, its element-node number.ufield::NTuple{Nu,Symbol}=()For each U-dof to entercost, its field.ainod::NTuple{Na,𝕫}=()For each A-dof to entercost, its element-node number.afield::NTuple{Na,Symbol}=()For each A-dof to entercost, its field.class:Symbol:Afor cost on A-dofs only,:I("instant") otherwise.cost::Functionifclass==:I,cost(X,U,A,t,costargs...)→ℝifclass==:A,cost(A,costargs...)→ℝXandUare tuples (derivates of dofs...), and∂0(X),∂1(X),∂2(X)must be used bycostto access the value and derivatives ofX(resp.U)[costargs::NTuple=() or NamedTuple] of additional arguments passed tocost``
Requestable internal variables
cost, the value of the cost.
Example
ele1 = addelement!(model,DofCost,[nod1],xinod=(1,),field=(:tx1,),
class=:I,cost=(X,U,A,t;X0)->(X[1]-X0)^2,costargs=(;X0=0.27)See also: SingleDofCost, ElementCost, addelement!
Muscade.DofLoad — TypeDofLoad{Tvalue,Field} <: AbstractElementAn element to apply a loading term to a single X-dof.
Named arguments to the constructor
field::Symbol.value::Function, wherevalue(t::ℝ) → ℝ.
Requestable internal variables
F, the value of the load.
Examples
using Muscade
model = Model(:TestModel)
node = addnode!(model,𝕣[0,0])
e = addelement!(model,DofLoad,[node];field=:tx,value=t->3t-1)Muscade.EigX — Typeeiginc = solve(EigX{ℝ};state=initialstate,nmod)
eiginc = solve(EigX{ℂ};state=initialstate,nmod)Given an initial (typicaly static) state initialstate, computes the lowest nmod eigenmodes of a system. EigX{ℝ} computes real eigenmodes not accounting for damping. EigX{ℝ} computes complex eigenmodes accounting for damping. The data structure eiginc can be passed to increment to obtain dynamic states superimposing mode shapes.
Input
initialstate- aStatenmod=5- the number of eigenmodes to identifydroptol=1e-9- in the stiffness and mass matrix, the magnitude of a term relative to the largest term in the matrix under which the term is set to zero.- Further named arguments: see the optional keyword arguments to
geneig.
Output
- an object of type
EigXℝincrementorEigXℂincrement, for use withincrementto create a snapshot of the oscillating system.
See also: solve, initialize!, increment, geneig
Muscade.EigXU — TypeEigXU{OX,OU}Study the combinations of load and response that are least detected by sensor systems.
An analysis is carried out by a call with the following syntax:
initialstate = initialize!(model)
eiginc = solve(EigXU{OX,OU};Δω, p, nmod,initialstate)The solver linearises the problem (computes the Hessian of the Lagrangian) at initialstate and solves the ΛXU-eigenvalue problem at frequencies ωᵢ = Δω*i with i∈{0,...,2ᵖ-1}.
Parameters
OX0 for static analysis 1 for first OX problems in time (viscosity, friction, measurement of velocity) 2 for second OX problems in time (inertia, measurement of acceleration)OU0 for white noise prior to the unknown load process 2 otherwise
Named arguments
dbg=(;)a named tuple to trace the call tree (for debugging).verbose=trueset to false to suppress printed output (for testing).initialstateaState.nmodthe number of eigen-modes to identusyΔωfrequency stepp2^psteps will be analysed.droptol=1e-10set to zero terms in the incremental matrices that are smaller thandroptolin absolute value.
Output
- an object of type
EigXUincrementfor use withincrementto create a snapshot of the oscillating system.
See also: increment,EigXU, solve, initialize!, studysingular, SweepX, DirectXUA
Muscade.ElementConstraint — TypeElementConstraint{Teleobj,λinod,λfield,Nu,Treq,Tg,Tgargs,Tmode} <: AbstractElementAn element to apply optimisation equality/inequality constraints on the element-results of another "target" element. The target element must not be added separately to the model. Instead, the ElementType, and the named arguments to the target element are provided as input to the ElementConstraint constructor.
This element generates a time varying optimisation constraint. For example: find A-parameters so that at all times, the element-result von-Mises stress does not exceed a given value.
The Lagrangian multiplier introduced by this optimisation constraint is of class :U
Named arguments to the constructor
λinod::𝕫The element-node number of the Lagrange multiplier.λfield::SymbolThe field of the Lagrange multiplier.reqA request for element-results to be extracted from the target element, see@request. The request is formulated as if adressed directly to the target element.gₛ::𝕣=1.A scale for the gap.λₛ::𝕣=1.A scale for the Lagrange multiplier.gapA gap functiongap(eleres,X,U,A,t,gargs...)→ℝ.eleresis the output of the above-mentionned request to the target element.XandUare tuples (derivates of dofs...), and∂0(X),∂1(X),∂2(X)must be used bycostto access the value and derivatives ofX(resp.U).X,UandAare the degrees of freedom of the elementElementType.gargs::NTupleAdditional inputs to the gap function.mode::Functionwheremode(t::ℝ) -> Symbol, with value:equal,:positiveor:offat any time. An:offconstraint will set the Lagrange multiplier to zero.ElementTypeThe named of the constructor for the relevant elementelementkwargsA named tuple containing the named arguments of theElementTypeconstructor.
Requestable internal variables
Not to be confused with the req provided as input to addelement! when adding an ElementConstraint, one can, after the analysis, request results from ElementConstraint
λThe constraints Lagrange multipliergapThe constraints gap functioneleres(...)where...is the list of requestables wanted from the target element. The "prefix"eleresis there to prevent possible confusion with variables requestable fromElementConstraint. For example@request gapwould extract the value of theElementConstraint's functiongap, while@request eleres(gap)refers to the value of a variable calledgapin the target element.
Example
@once gap(eleres,X,U,A,t) = eleres.Fh^2
ele1 = addelement!(model,ElementCoonstraint,[nod1];req=@request(Fh),
gap,λinod=1,λfield=:λ,mode=equal,
ElementType=AnchorLine,
elementkwargs=(Δxₘtop=[5.,0,0], xₘbot=[250.,0],L=290., buoyancy=-5e3))See also: Hold, DofConstraint, off, equal, positive, @request, @once
Muscade.ElementCost — TypeElementCost{Teleobj,Treq,Tcost,Tcostargs} <: AbstractElementAn element to apply costs on another "target" element's dofs and element-results. The target element must not be added separately to the model. Instead, the ElementType, and the named arguments to the target element are provided as input to the ElementCost constructor.
Named arguments to the constructor
reqA request for element-results to be extracted from the target element, see@request. The request is formulated as if adressed directly to the target element.costA cost functioncost(eleres,X,U,A,t,costargs...)→ℝ.eleresis the output of the above-mentionned request to the target element.XandUare tuples (derivates of dofs...), and∂0(X),∂1(X),∂2(X)must be used bycostto access the value and derivatives ofX(resp.U).X,UandAare the degrees of freedom of the elementElementType.[costargs::NTuple=() or NamedTuple]Additional arguments passed tocost.ElementTypeThe named of the constructor for the relevant element.elementkwargsA named tuple containing the named arguments of theElementTypeconstructor.
Requestable internal variables
Not to be confused with the req provided as input to addelement! when adding an ElementCost, one can, after the analysis, request results from ElementConstraint
costThe value ofcost(eleres,X,U,A,t,costargs...).eleres(...)where...is the list of requestables wanted from the target element. The "prefix"eleresis there to prevent possible confusion with variables requestable fromElementConstraint. For example@request costwould extract the value of theElementConstraint's functioncost, while@request eleres(cost)refers to the value of a variable calledcostin the target element.
Example
@once cost(eleres,X,U,A,t;Fh0) = (eleres.Fh-Fh0)^2
ele1 = addelement!(model,ElementCost,[nod1];req=@request(Fh),
cost=cost,
costargs = (;Fh0=0.27)
ElementType=AnchorLine,
elementkwargs=(Λₘtop=[5.,0,0], xₘbot=[250.,0], L=290., buoyancy=-5e3))See also: SingleDofCost, DofCost, @request, @once
Muscade.FreqXU — TypeFreqXU{OX,OU}A linear frequency domain solver for optimisation FEM.
An analysis is carried out by a call with the following syntax:
initialstate = initialize!(model)
stateXU = solve(FreqXU{OX,OU};Δt, p, t₀,tᵣ,initialstate)The solver linearises the problem (computes the Hessian of the Lagrangian) at initialstate with time tᵣ, and solves it at times t=range(start=t₀,step=Δt,length=2^p). The return
Parameters
OX0 for static analysis 1 for first order problems in time (viscosity, friction, measurement of velocity) 2 for second order problems in time (inertia, measurement of acceleration)OU0 for white noise prior to the unknown load process 2 otherwise
Named arguments
dbg=(;)a named tuple to trace the call tree (for debugging).verbose=trueset to false to suppress printed output (for testing).silenterror=falseset to true to suppress print out of error (for testing) .initialstateaState.t₀=0.time of first step.Δttime step.p2^psteps will be analysed.tᵣ=t₀reference time for linearisation.droptol=1e-10set to zero terms in the incremental matrices that are smaller thandroptolin absolute value.
Output
A vector of length 2^p containing the state of the model at each of these steps.
See also: solve, initialize!, studysingular, SweepX, DirectXUA
Muscade.FunctionFromVector — Typef = FunctionFromVector(xs::AbstractRange,ys::AbstractVector)
y = f(x)
Linear interpolation. Fails if `x` is outside the range `xs`Muscade.Hold — TypeHold <: AbstractElementAn element to set a single X-dof to zero.
Named arguments to the constructor
field::Symbol. The field of the X-dof to constraint.λfield::Symbol=Symbol(:λ,field). The field of the Lagrange multiplier.
Example
using Muscade
model = Model(:TestModel)
node = addnode!(model,𝕣[0,0])
e = addelement!(model,Hold,[node];field=:tx)See also: DofConstraint, DofLoad, DofCost
Muscade.IdVec — TypeAn "identity vector"
id = IdVec i = 9834987 id[i] == i # true for any i
See also Julia's identity function.
Muscade.Model — Typemodel = Model([ID=:my_model])Construct a blank model, which will be mutated to create a finite element [optimization] problem.
See also: addnode!, addelement!, describe, solve
Muscade.Monitor — TypeMonitor <: AbstractElementDebbuging tool: An element for for monitoring inputs to and outputs from another element, during an analysis.
Instead of adding the element to be monitored directly into the model, add this element with the element to be monitored as argument.
Inputs and outputs are @show'n.
Named arguments to the constructor
ElementTypeThe the type of element to be monitored-triggerA function that takesdbgas an input and returns a boolean (true) to printout.elementkwargsaNamedTuplecontaining the named arguments of theElementTypeconstructor.
Muscade.Node — TypeNodeThe eltype of vectors handed by Muscade as first argument to element constructors.
Example: function SingleDofCost(nod::Vector{Node};class::Symbol, ... )
See also: coord
Muscade.QuickFix — TypeQuickFix <: AbstractElementAn element for creating simple elements with "one line" of code. Elements thus created have several limitations:
- physical elements with only X-dofs.
- only
Rcan be espied.
The element is intended for testing. Muscade-based applications should not include this in their API.
Named arguments to the constructor
inod::NTuple{Nx,𝕫}. The element-node numbers of the X-dofs.field::NTuple{Nx,Symbol}. The fields of the X-dofs.res::Function, whereres(X::ℝ1,X′::ℝ1,X″::ℝ1,t::ℝ) → ℝ1, the residual.
Examples
A one-dimensional linear elastic spring with stiffness 2.
using Muscade
model = Model(:TestModel)
node1 = addnode!(model,𝕣[0])
node2 = addnode!(model,𝕣[1])
e = addelement!(model,QuickFix,[node1,node2];inod=(1,2),field=(:tx1,:tx1),
res=(X,X′,X″,t)->Svector{2}(2*(X[1]-X[2]),2*(X[2]-X[1])) )Muscade.SingleDofCost — TypeSingleDofCost{Derivative,Class,Field,Tcost} <: AbstractElementAn element with a single node, for adding a cost to a given dof.
Named arguments to the constructor
class::Symbol, either:X,:Uor:A.field::Symbol.cost::Function, wherecost(x::ℝ,t::ℝ[,costargs...]) → ℝifclassis:Xor:U, andcost(x::ℝ, [,costargs...]) → ℝifclassis:A.
[costargs::NTuple=() or NamedTuple] of additional arguments passed tocost``derivative::Int=00, 1 or 2 - which time derivative of the dof enters the cost.
Requestable internal variables
cost, the value of the cost.
Example
using Muscade
model = Model(:TestModel)
node = addnode!(model,𝕣[0,0])
e = addelement!(model,SingleDofCost,[node];class=:X,field=:tx,
costargs=(3.,),cost=(x,t,three)->(x/three)^2)See also: DofCost, ElementCost
Muscade.SingleUdof — TypeSingleUdof{XField,Ufield,Tcost} <: AbstractElementAn element that creates a Udof, and associates a cost to its value. The value of the Udof is applied as a load to a Xdof on the same node.
Named arguments to the constructor
Xfield::Symbol.Ufield::Symbol.cost::Function, wherecost(u::ℝ,t::ℝ[,costargs...]) → ℝ[costargs::NTuple=() or NamedTuple] of additional arguments passed tocost``
Requestable internal variables
cost, the value of the cost.
Example
using Muscade
model = Model(:TestModel)
node = addnode!(model,𝕣[0,0])
e = addelement!(model,SingleUdof,[node];Xfield=:tx,Ufield=:utx,
costargs=(3.,),cost=(x,t,three)->(x/three)^2)See also: DofCost, ElementCost
Muscade.SpyAxis — Typeaxis = Muscade.SpyAxis()Spoof a GLMakie Axis object so that calls like
lines!( axis,args...;kwargs...)result in args and kwargs being stored in axis, allowing to test functions that generate plots. Results are accessed by for example
axis.call[3].fun
axis.call[3].args[2]To get the name of the 3rd GLMakie function that was called, and the 2nd input argument of this call.
Only lines!, scatter! and mesh! logging functions are implemented for now, but more functions can easily be added.
Muscade.SweepX — TypeSweepX{ORDER}A non-linear, time domain solver, that solves the problem time-step by time-step. Only the X-dofs of the model are solved for, while U-dofs and A-dofs are unchanged.
SweepX{0}is Newton-Raphson, with feasibility line-search, to handle inequality constraints.SweepX{1}is implicit Euler, with feasibility line-search.SweepX{2}is Newmark-β, with Newton-Raphson iterations and feasibility line search
IMPORTANT NOTE: Muscade does not allow elements to have state variables, for example, plastic strain, or shear-free position for dry friction. Where the element implements such physics, this is implemented by introducing the state as a degree of freedom of the element, and solving for its evolution, even in a static problem, requires the use of ORDER≥1
An analysis is carried out by a call with the following syntax:
initialstate = initialize!(model)
setdof!(initialstate,1.;class=:U,field=:λcsr)
states = solve(SweepX{2};initialstate=initialstate,time=0:10)Named arguments to solve:
dbg=(;)a named tuple to trace the call tree (for debugging)verbose=trueset to false to suppress printed output (for testing)silenterror=falseset to true to suppress print out of error (for testing)initialstateaState, obtain fromìnitialize!orSweepX.timemaximum number of Newton-Raphson iterationsβ=1/4,γ=1/2parameters to the Newmark-β algorithm. Dummy ifORDER<2maxiter=50maximum number of equilibrium iterations at each step.maxΔx=1e-5convergence criteria: norm ofX. DmaxLλ=∞convergence criteria: norm of the residual.saveiter=falseset to true so that outputstatescontains the state at the iteration of the last step analysed. Useful to study a step that fails to converge.maxLineIter=50Maximum number of iteration in the feasibility line search. set to 0 to skip the line search (not recommended for models with inequality constraints).sfac=0.5Parameter in the line search for a feasible point. If a tentative result is not feasible, backtrack by a factorsfac. If still not feasible, backtrack what is left by a factorsfac, and so forth, up tomaxLineItertimes.γfac=0.5Parameter for feasibility. For an inequality constraintg(X)with reaction forceλ, requireg(X)*λ==γ, and multiplyγ *= γfacat each iteration.
Output
A vector of length equal to that of the named input argument time containing the states at the time steps.
See also: solve, initialize!, findlastassigned, studysingular, DirectXUA, FreqXU
Muscade.composeJacobian — TypecomposeJacobian{P}(Ty,X_)Given Ty obtained using revariate, and X_, obtained using motion{P}(X) where X is a tuple of SVectors and P=constants(X), compute y, a tuple of length ND of AbstractArrays of same eltype as vectors in X, andy∂X₀, the Jacobian of∂0(y)with respect to∂0(X)`.
See also revariate, motion, motion⁻¹, composevalue
Muscade.composevalue — Typecomposevalue{P,ND}(Ty,X_)Given Ty obtained using revariate, and X_, obtained using motion{P}(X) where X is a tuple of length ND and P=constants(X), compute y, a tuple of length ND of AbstractArrays of same eltype as vectors in `X.
See also revariate, motion, motion⁻¹, composeJacobian
Muscade.default — Typedefault{:fieldname}(namedtuple,defval)attempt to get a field fieldname from a NamedTuple. If namedtuple does not have such a field - or is not a NamedTuple, return defval.
Muscade.geneig — Typeλ,v,ncv = geneig{ALGO}(A,B,neig=5)Solves (A-λ*B)*v=0, finding the neig lowest eigenvalues λ (in absolute value) and the corresponding eigenvectors v (a Vector{Vector})
Input
ALGO can be
- :SDP if
Ais symmetric definite positive andBis symmetric. Will return realλandv. - :Hermitian if
Ais symmetric indefinite andBis symmetric. Will return realλandv. - :Complex otherwise, will return complex
λandv.
Optional keyword arguments:
maxiter = 300verbosity = 0 ∈ {0,1,2,3}krylovdim = 2neig+6
Uses KrylovKit.jl. Freely based on VibrationGEPHelpers.jl and input from PetrKryslUCSD and stevengj. See GIThub-blame for bug-credits.
Muscade.increment — Typestate = increment{OX}(initialstate,eiginc,imod,A)Starting from initalstate for which an EigX analysis has been carried out, and using the output eiginc of that analysis, construct new States representing the instantaneous state of the vibrating structure
Input
OXthe number of time derivatives to be computed.increment(initialstate,eiginc,imod,A)defaults toOX=2initialstatethe same initialStateprovided toEigXto computeeiginceigincobtained fromEigXimod, anAbstractVectorof integer mode numbersA, anAbstractVectorof same length asimod, containing real or complex amplitudes associated to the modes
Output
statea snapshot of the vibrating system
See also: EigX
Muscade.increment — Methodstate = increment{OX}(initialstate,eiginc,iω,imod,A)Starting from initalstate for which an EigX analysis has been carried out, and using the output eiginc of that analysis, construct new States representing the instantaneous state of the vibrating structure
Input
OXthe number of time derivatives to be computed.increment(initialstate,eiginc,imod,A)defaults toOX=2initialstatethe same initialStateprovided toEigXUto computeeiginceigincobtained fromEigXUiω, the number of the frequency to consider.ω=iω*ΔωwhereΔωis an input toEigXU.imod, anAbstractVectorof integer mode numbersA, anAbstractVectorof same length asimod, containing real or complex amplitudes associated to the modes
Output
statea snapshot of the vibrating system
See also: EigXU
Muscade.motion — MethodP = constant(X)
X_ = motion{P}(X)Transform a NTuple of SVectors, for example the vector X provided as an input to residual or Lagrangian into a SVector of ∂ℝ. This can be used by an element to compute time derivatives, for example Euler, Coriolis and centrifugal accelerations, or strain rates.
Some principles of safe automatic differentiation must be adhered to:
- the function that uses
motionmust also 'unpack' : no variable that is touched by the output ofmotionmust be returned by the function without having been unpacked bymotion⁻¹. Touched variables can for example be marked with an underscore. - The precendence
Pmust be calculated usingconstantswith all variables that are input to the function and may be differentiated. - If other levels of automatic differentiation are introduced within the function, unpack in reverse order of packing.
See motion⁻¹
Muscade.motion⁻¹ — MethodP = constants(X,U,A,t)
ND = length(X)
X_ = motion{P,ND}(X)
Y_ = f(Y_)
Y₀ = motion⁻¹{P,ND,0}(Y_)
Y₁ = motion⁻¹{P,ND,1}(Y_)
Y₂ = motion⁻¹{P,ND,2}(Y_)
Y = motion⁻¹{P,ND }(Y)Extract the value and time derivatives from a variable that is a function of the output of motion. In the above Y is a tuple of length ND. One can use ∂0,∂1 and ∂2 to unpack Y.
See also motion
Muscade.revariate — MethodTX = revariate{O}(X)The vector X of Reals (possibly: ∂ℝs) is stripped of its partials, an revariated to the order precedence(X)+O.
TX = revariate(X)revariates to the order precedence(X).
revariate, in conjunction with compose can be used to improve performance when the length of X is smaller than the length of its partials.
Be extremely careful never to mix any variable that is a function of X with any other variables containing ∂ℝs but not produced by the same revariate.
See also: compose
Muscade.value — Methody = value{P}(Y)Extract the value of an automatic differentiation object, or SArray of such objects.
Muscade.value_∂ — Methody,yₓ = value_∂{P,N}(Y)
y,y′ = value_∂{P }(Y)Get value and derivative in one operation.
Muscade.variate — MethodX = variate{P,N}(x)where typeof(x)<:SVector{N}, create a SVector of automatic differentiation objects of precedence P.
X = variate{P}(x)where typeof(x)<:Real, create an object of precedence P.
Muscade.δ — MethodX = δ{P,N,R}()create a SVector of automatic differentiation objects of precedence P and value zero.
X = δ{P}()Create automatic differentiation object of precedence P and value zero.
Muscade.ℂ — Typeℂ (\bbC)an alias for abstract type Complex{<:Real}. For use in dispatching. ℂ1... ℂ4 are AbstractArrays of dimensions 1 to 4. ℂ11 is an AbstractVector of AbstractVector.
Muscade.ℕ — Typeℕ (\bbN)an alias for UInt64. For use in dispatching. ℕ1... ℕ4 are AbstractArrays of dimensions 1 to 4.
Muscade.ℝ — Typeℝ (\bbR)an alias for abstract type Real. For use in dispatching. ℝ1... ℝ4 are AbstractArrays of dimensions 1 to 4. ℝ11 is an AbstractVector of AbstractVector.
Muscade.ℤ — Typeℤ (\bbZ)an alias for abstract type Integer. For use in dispatching. ℤ1... ℤ4 are AbstractArrays of dimensions 1 to 4. ℤ11 is an AbstractVector of AbstractVector.
Muscade.∂ — Methodyₓ = ∂{P,N}(Y)Extract the gradient of an automatic differentiation object. If Y is a SArray, the index of the partial derivative is appended to the indices of Y.
y′ = ∂{P}(Y)Extract the derivative of an automatic differentiation object (or SArray of such), where the variation was created by the syntax variate{P}.
Muscade.𝔹 — Type𝔹 (\bbB)an alias for Bool. For use in dispatching. 𝔹1... 𝔹4 are AbstractArrays of dimensions 1 to 4.
Muscade.𝕓 — Type𝕓 (\bbb)an alias for Bool. For use in struct definitions. 𝕓1... 𝕓4 are Arrays of dimensions 1 to 4.
Muscade.𝕔 — Type𝕔 (\bbc)an alias for Complex{Float64}. For use in struct definitions. 𝕔1... 𝕔4 are Arrays of dimensions 1 to 4. 𝕔11 is a Vector of Vector.
Muscade.𝕟 — Type𝕟 (\bbn)an alias for UInt64. For use in struct definitions. 𝕟1... 𝕟4 are Arrays of dimensions 1 to 4.
Muscade.𝕣 — Type𝕣 (\bbr)an alias for Float64. For use in struct definitions. 𝕣1... 𝕣4 are Arrays of dimensions 1 to 4. 𝕣11 is a Vector of Vector.
Muscade.𝕫 — Type𝕫 (\bbz)an alias for Int64. For use in struct definitions. 𝕫1... 𝕫4 are Arrays of dimensions 1 to 4. 𝕫11 is a Vector of Vector.
Functions
Muscade.:∘₁ — Methodc = a∘₁bCompute the single-dot product of two arrays, so that cᵢⱼ=Σₖ aᵢₖ bₖⱼ where i and j can be multiple indices.
Muscade.:∘₂ — Methodc = a∘₂bCompute the double-dot product of two arrays, so that cᵢⱼ=Σₖₗ aᵢₖₗ bₖₗⱼ where i and j can be multiple indices.
Muscade.:⊗ — Methodc = a⊗bCompute the exterior product of two arrays, so that cᵢⱼ=aᵢ bⱼ where i and j can be multiple indices.
Muscade.GUI — MethodGUI(eiginc,initialstate;[draw_shadow=true],[shadow=...],[model=...])Taking the output eiginc obtained from an EigXU, and the state initstate provided to EigXU, provide a GUI to explore the results.
Optional keyword arguements are
draw_shadowwhether to superimpose a drawing ofinitstateshadowaNamedTuplewith any arguments to be passed todraw!initstatemodelaNamedTuplewith any arguments to be passed todraw!theEigXUmodes.
See also EigXU
Muscade.McLaurin — MethodMcLaurin(Ty,x)Ty::∂ℝ has partials to arbitrary order with respect to a variable x. These partials define a McLaurin expansion, which McLaurin evaluates at value x, as if Ty had been computed at 0.
McLaurin handles nested structures of Tuples and SVectors of ∂ℝ, applying the expansion to each element.
Muscade.QuadraticFunction — Methodf = QuadraticFunction(μ,σ)μ and σ are 𝕣 (Float64)
y = f(x) # == 1/2*((x-μ)/σ)^2
f = QuadraticFunction(μ,σ)Alternatively, μ can be a Function of time, in which case
y = f(x,t) # == 1/2*((x-μ(t))/σ)^2Muscade.Taylor — MethodTaylor(Ty,x₀,x)Ty::∂ℝ has partials to arbitrary order evaluated at x₀. These partials define a Taylor expansion, which Taylor evaluates at value x
Taylor handles nested structures of Tuples and SVectors of ∂ℝ, applying the expansion to each element.
Muscade.VALUE — Method@show VALUE(Y)Completely strip Y of partial derivatives. Use only for debugging purpose.
Muscade.addelement! — Methodeleid = addelement!(model,ElType,nodid;kwargs...)Add one or several elements to model, connecting them to the nodes specified by nodid.
If nodid is an AbstractVector: add a single element to the model. eleid is then a single element identifier.
If nodid is an AbstractMatrix: add multiple elements to the model. Each row of nodid identifies the node of a single element. eleid is then a vector of element identifiers.
For each element, addelement! will call eleobj = ElType(nodes;kwargs...) where nodes is a vector of nodes of the element.
Muscade.addin! — Methodaddin!(asm,global,block,ibr,ibc,factor=1.)Add a sparse block into a large out sparse matrix, at block-row and -column ibr and ibc. Use prepare to allocate memory for global and build the assembler asm.
Muscade.addin! — Methodaddin!(asm,outvec,blockvec,ibr)Add a full block vector into a large outvec full vector. at block-row ibr. Use prepare to create asm.
See also: prepare
Muscade.addnode! — Methodnodid = addnode!(model,coord)If coord is an AbstractVector of Real: add a single node to the model. Muscade does not prescribe what coordinate system to use. Muscade will handle to each element the coord of the nodes of the element, and the element constructor must be able to make sense of it. nodid is a node identifier, that is used as input to addelement!.
If coord is an AbstractMatrix, its rows are treated as vectors of coordinates. nodid is then a vector of node identifiers.
See also: addelement!, coord , describe
Muscade.allocate_drawing — Methodmut,opt = Muscade.allocate_drawing(axis,eleobjs;kwargs...)Elements that are to be displayed in graphical output must implement a method for Muscade.allocate_drawing.
The method is to allocate opt, a NamedTuple of data that will not be mutated from frame to frame, but are usefull in Muscade.update_drawing or Muscade.display_drawing!.
The method is also to allocate mut, a NamedTuple of data that will be mutated from frame to frame. When implementing graphics with GLMakie.jl, the fields of mut must be exactly the updatable inputs provided to GLMakie.jl's drawing primitives: in Muscade.display_drawing!
lines!(axis,mut.x,mut.y)is acceptable, but
lines!(axis,mut.x[:,s],mut.y[:,s])
lines!(axis,mut.a.x,mut.a.y)are not.
The content of Arrays in opt and mut can be undef-ined.
Inputs are:
axisthe "canvas" to draw on, typicaly aGLMakie.jlAxis.eleobjsanAbstractVectorof element objects, of lengthnel.kwargsaNamedTuplecontaining the keyword arguments provided by the user. Seedefault.
See also: Muscade.update_drawing, Muscade.display_drawing!
Muscade.colnormalize — Methodcolnormalize(a)Euclidian-normalize the columns of an SMatrix
Muscade.columnmatrix — Methodcolumnmatrix(v)Reshape a vector into a matrix of size (length(v),1)
Muscade.compose — Methodcompose(Ty,x)Compose automatic differentiation. For example Tx = revariate(x) Ty = f(Tx) y = compose(Ty,x) is faster than y = f(x) if the length of x is smaller than the length of its partials.
Muscade.constants — MethodP = constants(a,b,c)Generate a precedence P that is higher than the precedence of the arguments.
Muscade.coord — Methodc = coord(node)Used by element constructors to obtain the coordinates of a vector of Nodes handed by Muscade to the constructor. c is accessed as
c[inod][icoord]where inod is the element-node number and icoord an index into a vector of coordinates.
Note that c[inod] points at the same memory as nod[inod].coord: do not mutate c[inod]!
See also: addnode!, addelement!, describe, solve
Muscade.describe — Methoddescribe(model,spec)Print out information about model. spec can be
- an
EleIDto describe an element, - a
DofIDto describe a dof. - a
NodIDto describe a node, :doftypto obtain a list of doftypes,:dofto obtain a list of dofs or:eletypfor a list of element types.
See also: addelement!, addnode!
Muscade.describe — Methoddescribe(state;class=:all)Provide a description of the dofs stored in state. class can be either :all, :Λ, :ΛX, :X, :U, :A or :scale
See also: solve
Muscade.diffed_lagrangian — Methoddiffed_lagrangian(eleobj;Λ,X,U,A,t=0.,SP=nothing)Compute the Lagrangian, its gradients and Hessian, and the memory of an element. For element debugging and testing.
The output is a NamedTuple with fields Λ, X, U, A, t, SP echoing the inputs and fields
∇Lof format∇L[iclass][ider]so that for example∇L[2][3]contains the gradient of the Lagrangian wrt to the acceleration.iclassis 1,2,3 and 4 forΛ,X,UandArespectively.HLof formatHL[iclass,jclass][ider,jder]so that for exampleHL[1,2][1,3]contains the mass matrix.FBas returned bylagrangian
See also: diffed_residual, print_element_array
Muscade.diffed_residual — Methoddiffed_residual(eleobj;X,U,A,t=0.,SP=nothing)Compute the residual, its gradients, and the memory of an element. For element debugging and testing.
The output is a NamedTuple with fields X, U, A, t, SP echoing the inputs and fields
Rcontaining the residual∇Rof format∇R[iclass][ider]so that for example∇R[2][3]contains the mass matrix.iclassis 2,3 and 4 forX,UandArespectively.FBas returned byresidual
See also: diffed_lagrangian, print_element_array
Muscade.display_drawing! — MethodMuscade.display_drawing!(axis,MyElement,mut,opt)Elements that are to be displayed in graphical output must implement a method for Muscade.display_drawing!.
Inputs are:
axisthe "canvas" to draw on, typicaly aGLMakie.jlAxis.MyElementused for dispatching to the right method.mutis aNamedTuple, as output byMuscade.update_drawing. More specificaly, if implementing graphics withGLMakie.jl,muthas beenoptis as returned byMuscade.allocate_drawing
When implementing graphics with GLMakie.jl, the fields of mut must be exactly the updatable inputs provided to GLMakie.jl's drawing primitives: in Muscade.display_drawing!
lines!(axis,mut.x,mut.y)is acceptable, but
lines!(axis,mut.x[:,s],mut.y[:,s])is not. The reason is that when doing graphics with GLMakie.jl, Muscade will recursively wrap each field of mut into an Observable before calling the elements' methods display_drawing!. This allows Muscade to update the graphics by just calling Muscade.update_drawing for each element.
See also: Muscade.allocate_drawing, Muscade.update_drawing
Muscade.doflist — MethodMuscade.doflist(::Type{E<:AbstractElement})Elements must provide a method for Muscade.doflist.
The method must take the element type as only input, and return a NamedTuple with fieldnames inod,class and field. The tuple-fields are NTuples of the same length. For example
Muscade.doflist( ::Type{<:Turbine}) = (inod =(1 ,1 ,2 ,2 ),
class=(:X ,:X ,:A ,:A ),
field=(:tx1,:tx2,:Δseadrag,:Δskydrag))In Λ, X, U and A handed by Muscade to residual or lagrangian, the dofs in the vectors will follow the order in the doflist. Element developers are free to number their dofs by node, by field, or in any other way.
See also: Muscade.lagrangian, Muscade.residual, Muscade.nosecondorder
Muscade.draw! — Methodgraphic = draw!(axis ,state[,els];kwargs...)
draw!(graphic,state[,els];kwargs...)Plot all or part of a Model.
Currently, only GLMakie.jl is supported and tested, but Muscade is designed to allow application developers to chose other graphic system, including exporting data to Paraview. GLMakie.jl is thus not a dependency of Muscade, and must be installed and invoked (using) separately to run demos provided with Muscade.
Application developers can implement methods Muscade.allocate_drawing, Muscade.update_drawing and Muscade.display_drawing! to make their element "drawable".
axis a GLMakie.jl Axis, a Muscade.SpyAxis (for automated testing of graphic generation), and in the future a HDF5/VTK file handle for export of data to Paraview. state a single State. els specifies which elements to draw and can be either
- a vector of
EleIDs (obtained fromaddelement!`), all corresponding to the same concrete element type - a concrete element type (see
eletyp). - omitted: all the element of the model are drawn.
kwargs... is any additional key words arguments that will be passed to the draw method of each element, for example to specify colors, etc. See the elements' documentation.
When a plot of the Model is first generated, axis must be provided, and draw! returns graphic. graphic can then be provided for further calls to draw! to update the graphic.
See also: getdof, @request, @espy, addelement!, solve
Muscade.eletyp — Methodet = eletyp(model)Return a vector of the concrete types of elements in the model.
Muscade.equal — Methodequal(t) → :equalA function which for any value t returns the symbol equal. Usefull for specifying the keyword argument mode=equal in adding an element of type `DofConstraint to a Model.
See also: DofConstraint, ElementConstraint, off, positive
Muscade.fast — Methody,... = fast(f,x)In the context of forward automatic differentiation using ∂ℝ, accelerate the evaluation of y,...= f(x) if the length of x is smaller than the length of its partials.
Be extremely careful with closures, making sure that f does not capture variables of type ∂ℝ.
Muscade.findlastassigned — Methodilast = findlastassigned(state)Find the index ilast of the element before the first non assigment element in a vector state.
In multistep analyses, solve returns a vector state of length equal to the number of steps requested by the user. If the analysis is aborted, solve still returns any available results at the begining of state, and the vector state[1:ilast] is fully assigned.
See also: solve
Muscade.getdof — Methoddofres = getdof(state;[class=:X],field=:somefield,nodID=[nodids...],[order=0])Obtain the value of dofs of the same class and field, at various nodes and for various states.
If state is a vector, the output dofres has size (ndof,nstate). If state is a scalar, the output dofres has size (ndof,).
Muscade.getndof — Methodgetndof(model|Element)
getndof(model|Element,class)
getndof(model|Element,(class1,class2,[,...]))where class can be any of :X, :U, :A: get the number of dofs of each specified dof-classes for the variable model or the type Element. If no class is specified getndof return the asum of the number of dofs of all classes.
See also: describe
Muscade.getresult — Methodeleres = getresult(state,req,els)Obtain an array of nested NamedTuples and NTuples of element results. req is a request defined using @request. state a vector of States or a single State. els can be either
- a vector of
EleIDs (obtained fromaddelement!) all corresponding to the same concrete element type - a concrete element type (see
eletyp).
If state is a vector, the output dofres has size (nele,nstate). If state is a scalar, the output dofres has size (nele).
See also: getdof, @request, @espy, addelement!, solve, eletyp
Muscade.getsomedofs — Methodrotations = getsomedofs(X,[3,6])Used by elements' residual or lagrangian to some degrees of freedom, and their time derivatives, from the variables X and U.
Muscade.getδt — Methodgetδt(n,δω) = 2π/(n*δω)
`n` is the length of the time seriesMuscade.getδω — Methodδω=getδω(n,δt) = 2π/(n*δt)
`n` is the length of the time seriesMuscade.initialize! — Methodinitialstate = initialize!(model)Return an initial State for the model with all dofs set to zero
Modifying a model (invoquing addnode! and addelement! after initialize! will result in an error)
Optional keyword arguments: nΛder=1, nXder=1, nUder=1 to specify the number of "derivatives" to store in the State. note that "n⋅der==order+1", that is, for a dynamic problem (with accelerations), nXder=3 so that order==2. Setting n⋅der is only required if setdof! will be used. A dynamic solver handles a "static" initial state perfectly well. time=-∞ the time associated to the initial state. Note that for example setting time=0., and then calling a solver with a first time step also at 0. causes an error.
See also: setdof!, Model, addnode!, addelement!, solve
Muscade.lagrangian — Method@espy function Muscade.lagrangian(eleobj::MyElement,Λ,X,U,A,t,SP,dbg)
...
return L,FB
endElements must implement a method for Muscade.lagrangian or Muscade.residual.
Inputs
eleobjan element objectΛaSVector{nXdof,R} where{R<:Real}, Lagrange multipliers (akaδXvirtual displacements).XaNTupleofSVector{nXdof,R} where{R<:Real}, containing the Xdofs and, depending on the solver, their time derivatives. Usex=∂0(X),v=∂1(X)anda=∂2(X)to safely obtain vectors of zeros where the solver leaves time derivatives undefined.UaNTupleofSVector{nUdof,R} where{R<:Real}, containing the Udofs and, depending on the solver, their time derivatives. Useu=∂0(U),̇u=∂1(U)and̈u=∂2(U)to safely obtain vectors of zeros where the solver leaves time derivatives undefined.AaSVector{nAdof,R} where{R<:Real}.ta `Realcontaining the time.SPsolver parameters (for example: the barrier parameterγfor interior point methods).dbgaNamedTupleto be used only for debugging purposes.
Outputs
Lthe lagrangianFBfeedback from the element to the solver (for example: canγbe reduced?). ReturnnoFBof the element has no feedback to provide.
See also: Muscade.residual, Muscade.doflist, @espy, ∂0, ∂1, ∂2, noFB,
Muscade.mergerequest — Methodreq = mergerequest(o.req)"Outer" elements like ElementCost and ElementConstraint use requests to apply a cost or a constraint to requestables from another "target" element. These outer elements must be coded carefully so that getresult can be used to extracted both requestable internal results from the outer and from the target element.
mergerequest is used to merge the requests for the request needed to enforce a cost or constraint, and the user's request for element to be obtained from the analysis. The call to mergerequest, to be inserted in the code of lagrange for the outer element will be modified by @espy to something like req = mergerequest(o.req,req), to merge o.req of the outer element to any requests req transmitted by the user to extract results (or by an outer element to the outer element).
See the code of ElementCost's constructor and lagrange method for an example.
See also: ElementCost, @request, getresult
Muscade.mod_onebased — Methodmod_onebased(i,n) = mod(i-1,n)+1For i::ℤ, returns a value in {1,...n}. This differs from mod which return a value in [0,n[
Muscade.muscadeerror — Methodmuscadeerror([[dbg,]msg])Throw a MuscadeException, where
dbgis aNamedTuplethat contains "location information"
(for example: solver, step, iteration, element, quadrature point) that will be displayed with the error message.
msgis aStringdescribing the problem.
Muscade.nosecondorder — Methodnosecondorder(::Type{E<:AbstractElement})Elements that define residual which would give excessive compilation and/or execution time if differentiated to the second order can implement a method after the below pattern to limit differentiation to first order:
Muscade.nosecondorder( ::Type{<:MyElementType}) = Val(true)Muscade.off — Methodoff(t) → :offA function which for any value t returns the symbol off. Usefull for specifying the keyword argument mode=off in adding an element of type `DofConstraint to a Model.
See also: DofConstraint, ElementConstraint, equal, positive
Muscade.positive — Methodpositive(t) → :positiveA function which for any value t returns the symbol positive. Usefull for specifying the keyword argument mode=positive in adding an element of type `DofConstraint to a Model.
See also: DofConstraint, ElementConstraint, off, equal
Muscade.prepare — Methodbigmat,bigmatasm,bigvecasm,bigvecdis = prepare(pattern)Prepare for the assembly of sparse blocks into a large sparse matrix. bigmat is allocated, with the correct sparsity structure, but its nzval undef'ed. Where some blocks share the same sparsity structure, blocks in pattern can have === elements.
pattern is a SparseMatrixCSC{<:SparseMatrixCSC}, where empty blocks are structuraly zero
See also: addin!
Muscade.print_element_array — Methodprint_element_array(eleobj,class,V)Show a vector (or a matrix) V, the rows of V being described as corresponding to eleobj dof of class class. This can be used to print degrees of freedom, residuals, their derivatives, or gradients and Hessian of the Lagrangian.
See also: diffed_residual, diffed_lagrangian
Muscade.residual — Method@espy function Muscade.residual(eleobj::MyElement,X,U,A,t,SP,dbg) ... return R,FB end
Elements must implement a method for Muscade.residual or Muscade.lagrangian.
Inputs
eleobjan element objectXaNTupleofSVector{nXdof,R} where{R<:Real}, containing the Xdofs and, depending on the solver, their time derivatives. Usex=∂0(X),v=∂1(X)anda=∂2(X)to safely obtain vectors of zeros where the solver leaves time derivatives undefined.UaNTupleofSVector{nUdof,R} where{R<:Real}, containing the Udofs and, depending on the solver, their time derivatives. Useu=∂0(U),̇u=∂1(U)and̈u=∂2(U)to safely obtain vectors of zeros where the solver leaves time derivatives undefined.AaSVector{nAdof,R} where{R<:Real}.ta `Realcontaining the time.SPsolver parameters (for example: the barrier parameterγfor interior point methods).dbgaNamedTupleto be used only for debugging purposes.
Outputs
Rthe residualFBfeedback from the element to the solver (for example: canγbe reduced?). ReturnnoFBof the element has no feedback to provide.
See also: Muscade.lagrangian, Muscade.nosecondorder, Muscade.doflist, @espy, ∂0, ∂1, ∂2, noFB
Muscade.rowmatrix — Methodrowmatrix(v)Reshape a vector into a matrix of size (1,length(v))
Muscade.setdof! — Methodstate = setdof!(state,value ;[class=:X],field=:somefield, [order=0])
state = setdof!(state,value::Vector;[class=:X],field=:somefield,nodID=[nodids...],[order=0])Set the value of dofs of the same class and field, at various nodes and for various states. There are two methods:
- A single
valueis applied to all relevant nodes in the model valueandnodIDare vectors of the same lengths, and each element invalueis applied to the corresponding node.
setdof! is peculiar in that it modifies its input state variable, but must be used as a function. A call like stateout = setdof!(statein,value;class=:X,field=:somefield,order=1) can turn out in two ways: If the state already stores derivatives in X to order 1, then statein is mutated and statein===stateout. Otherwise, statein is unchanged, stateout is a new object, sharing as much memory as possible with statein. To avoid confusion, always use the syntax shown above.
Muscade.setscale! — Methodsetscale!(model;scale=nothing,Λscale=nothing)Provide scale value for each type (class and field) of dof in the model. This is usued to improve the conditioning of the incremental problems and for convergence criteria. scale is a NamedTuple with fieldnames within X, U and A. Each field is itself a NamedTuple with fieldnames being dof fields, and value being the expected order of magnitude.
For example scale = (X=(tx=10,rx=1),A=(drag=3.)) should be read as: X-dofs of field :tx are expected to be of the order of magnitude of 10m in the solution, :rx to be of the order of 1 radian, and A-dofs of field drag of the order of 3. All other degrees of freedom are of the order of 1.
Determining scaling coefficients that improve the condition number of incremental matrices is a hard problem.
Λscale is a scalar. The scale of a Λ-dof will be deemed to be the scale of the corresponding X-dof, times Λscale.
See also: addnode!, describe, coord, studyscale
Muscade.solve — Methodsolve(Solver;dbg=(;),verbose=true,silenterror=false,kwargs...)Execute an analysis using solver Solver (e.g. SweepX, DirectXUA...), and safeguard partial results in the case of error.
Named arguments
dbg=(;)a named tuple to trace the call tree (for debugging)verbose=trueset to false to suppress printed output (for testing)silenterror=falseset to true to suppress print out of error (for testing)kwargs...Further arguments passed on to the methodsolveprovided by the solver
See also: SweepX, DirectXUA, initialize!
Muscade.sparser! — Methodsparser!(S::SparseMatrixCSC,keep::Function)Eliminate terms that do not satisfy a criteria from the storage of a sparse matrix. S will be mutated. keep is a Function which to an index into S.nzval associate true if storage is to be kept for this term and false otherwise. Alternatively, keep can be a Vector{Bool}
Examples
sparser!(S,i->abs(S.nzval[i])>tol)
sparser!(S,keep)
sparser!([S1,S2],1e-9)
sparser!(S1,S2],1e-9)In the first example, the keep function accesses S.nzval[i], and the term is then mutated by sparser!. Any criteria requiring multipe access to nzval must build a Vector before calling sparser!.
Note that assemble! computes the nzval of a sparse, assumning that its sparsity structure colptr and rowval is unchanged since sparse storage was allocated by asmmat in prepare. In other words, if applying sparser! directly to a sparse returned by assemble!, assemble! can no longer be called for this matrix. In that case,
- deepcopy the returned matrix
- apply
sparser!to the copy - after a new call to
assemble!usekeepwhen copyingnzval
Muscade.studyscale — Methodscale = studyscale(state;[SP=nothing],[verbose=false],[dbg=(;)])Returns a named tuple of named tuples for scaling the model, accessed as scaled.myclass.myfield, for example scale.X.tx1.
If verbose=true, prints out a report of the analysis underlying the proposed scale. The proposed scaling depends on the state passed as input - as it is computed for a given incremental matrix.
See also: setscale!
Muscade.studysingular — Methodmatrix = studysingular(state;SP,[iclasses=(Λ,:X,:U,:A)],[jclasses=iclasses],[verbose::𝕓=true],[dbg=(;)])Generates an incremental matrix for state (no time derivatives) corresponding to the classes required, and report on the null space of the matrix.
To do so, the incremental matrix is converted to full format, limiting the applicability to small models.
The function returns the incremental matrix.
Muscade.toggle — Methodtoggle(condition,a,b)Typestable equivalent of condition ? a : b. Returns a value converted to promote_type(typeof(a),typeof(b))
Muscade.update_drawing — Methodmut = Muscade.update_drawing( axis,::AbstractVector{E},oldmut,opt, Λ,X,U,A,t,SP,dbg)Elements that are to be displayed in graphical output must implement a method for Muscade.allocate_drawing.
For parametric element types
Muscade.update_drawing(axis,o::AbstractVector{Teleobj}, Λ,X,U,A,t,SP,dbg;kwargs...)
where{Teleobj<:MyElement}For non-parametric element types, one can simplify the above to:
Muscade.update_drawing(axis,o::AbstractVector{MyElement}, Λ,X,U,A,t,SP,dbg;kwargs...)Inputs are:
axisthe "canvas" to draw on, typicaly aGLMakie.jlAxis.eleobjsanAbstractVectorof element objects, of lengthnel.oldmutthe outputmutofMuscade.allocate_drawingor of a previous call toMuscade.update_drawing.optthe outputoptofMuscade.allocate_drawingΛa matrix of size(nXdof,nel)XaNTuple(over the derivatives) of matrices of size(nXdof,nel)UaNTuple(over the derivatives) of matrices of size(nUdof,nel)Aa matrix of size(nAdof,nel)ttimeSPsolver parametersdbgdebuging informationkwargsaNamedTuplecontaining the keyword arguments provided by the user. Seedefault.
See also: Muscade.allocate_drawing, Muscade.display_drawing!
Muscade.∂0 — Methodposition = ∂0(X)Used by elements' residual or lagrangian to extract the zero-th order time derivative from the variables X and U.
See also: ∂1,∂2,getsomedofs
Muscade.∂1 — Methodvelocity = ∂1(X)Used by elements' residual or lagrangian to extract the first order time derivative from the variables X and U. Where the solver does not provide this derivative (e.g. a static solver), the output is a vector of zeros.
See also: ∂0,∂2,getsomedofs
Muscade.∂2 — Methodposition = ∂2(X)Used by elements' residual or lagrangian to extract the zero-th order time derivative from the variables X and U. Where the solver does not provide this derivative (e.g. a static solver), the output is a vector of zeros.
See also: ∂0,∂1,getsomedofs
Muscade.𝔉 — MethodX = 𝔉(x,δt) # typeset with \mfrakF\BbbrFourrier transform of a real time series x stored at time steps δt and length 2N = 2*2^p into a complex spectre X stored at frequency intervals δω=getδω(2N,δt)=2π/(2N*δt). The length of the spectre is N: only positive frequencies are stored (the Fourrier transform of real functions are Hermitian).
This provides a discretization of the unitary Fourrier transform,
G(ω) = 𝔉(g)(ω) = 1/√(2π) ∫exp(-𝑖ωt) g(t) dt𝔉 is unitary, in the sense that
sum(abs2.(x))*δt ≈ 2*(sum(abs2.(X)) - abs2.(X[1])/2)*δω(since the discrete spectre is provided for ω≥0, it contains only half the energy)
Arguments
xa vector of real numbers representing a time series. Its length must be a power of two.δtthe time step of the time series
Example
X = 𝔉(x,δt)
δω = getδω(length(x),δt)
x′ = 𝔉⁻¹(X,δω) # ≈ xMuscade.𝔉⁻¹ — Methodx = 𝔉⁻¹(X,δω) # typeset with \mfrakF\^-\^1See 𝔉
Arguments
Xa vector of complex numbers representing one side of a spectra. Its length must be a power of two.δω, the angular frequency step of spectra
Example
X = 𝔉(x,δt)
δω = getδω(length(x),δt)
x′ = 𝔉⁻¹(X,δω) # ≈ xMuscade.𝕫log2 — Method𝕫log2(i::𝕫)Compute the integer log2 of an integer, fails if i is not a power of two.
Macros
Muscade.@espy — Macro@espy function ... endFrom an anotated function code, generate - "clean" code, in which the anotations have been deleted, and with the call syntax argout... = foo(argin...) - "espying" code, with added input and ouput arguments argout...,res = foo(argin...,req) where req has been generated using @request and res is a nested structure of NamedTuples and NTuples containing the requested data.
The macro is not general: it is designed for residual and lagrangian, which for performance have to be programmed in "immutable" style: they must never mutate variables (this implies in particular, no adding into an array in a loop over Gauss points). So @espy only supports the specific programming constructs needed in this style.
The following is an example of anotated code:
@espy function residual(x::Vector{R},y) where{R<:Real}
ngp=2
accum = ntuple(ngp) do igp
☼z = x[igp]+y[igp]
☼s,☼t = ☼material(z)
♢square = s^2
@named(s)
end
r = sum(i->accum[i].s,ngp)
return r,nothing,nothing
end- The keyword
functionis preceded by the macro-call@espy. - The name of requestable variables is preceded by
☼(\sun). Such anotation must always appear on the left of an assigment. - If the name of a variable is preceded by
♢(\diamond), then the variable is evaluated only if requested. Such a notation can only be used if there is only one variable left of the assignement. - The name of a function being called must be preceded by
☼if the definition of the function is itself preceeded by the macro-call@espy. for-loops are not supported.do-loops must be used: to be efficient,residualandlagrangianmust not allocate and thus use immutables.- The keyword
returnmust be explicitly used, and if must be followed the a comma separated list of output variables. Syntaxes likereturn if...are not supported.
Muscade.@espydbg — Macro@espydbg function ... endGenerate the same code as @espy and print it (for debug purposes).
Muscade.@once — Macro@once tag f(x)= x^2do not parse the definition of function f again if not modified. Using in a script, this prevents recompilations in Muscade or applications based on it when they receive such functions as argument.
tag must be a legal variable name, and unique to this invocation of @once
Muscade.@request — Macroreq = @request exprCreate a request of internal results wanted from a function. Considering the function presented as example for @espy, examples of possible syntax include
req = @request gp(s,z,material(a,b))
req = @request gp(s)
req = @request gp(material(a))The first expression can be read as follows: "In the function, there is a do loop over variable igp, and within this loop a call to a function material. Results s and z are wanted from within the loop, and results a and b from within material.
The corresponding datastructure containing the results for each element is a nesting of NTuples and NamedTuples, and can be accessed as out.gp[igp].material.a and so forth.
Muscade.@typeof — Macroinftyp,rettyp = @typeof(foo(args...[;kwargs...]))
Determine the inferred type and the returned type of the output[s] returned by the relevant method-instance of foo.Index
Muscade.noFBMuscade.ϵMuscade.∞Muscade.AbstractElementMuscade.DirectXUAMuscade.DofConstraintMuscade.DofCostMuscade.DofLoadMuscade.EigXMuscade.EigXUMuscade.ElementConstraintMuscade.ElementCostMuscade.FreqXUMuscade.FunctionFromVectorMuscade.HoldMuscade.IdVecMuscade.ModelMuscade.MonitorMuscade.NodeMuscade.QuickFixMuscade.SingleDofCostMuscade.SingleUdofMuscade.SpyAxisMuscade.SweepXMuscade.composeJacobianMuscade.composevalueMuscade.defaultMuscade.geneigMuscade.incrementMuscade.incrementMuscade.motionMuscade.motion⁻¹Muscade.revariateMuscade.valueMuscade.value_∂Muscade.variateMuscade.δMuscade.ℂMuscade.ℕMuscade.ℝMuscade.ℤMuscade.∂Muscade.𝔹Muscade.𝕓Muscade.𝕔Muscade.𝕟Muscade.𝕣Muscade.𝕫Muscade.:∘₁Muscade.:∘₂Muscade.:⊗Muscade.GUIMuscade.McLaurinMuscade.QuadraticFunctionMuscade.TaylorMuscade.VALUEMuscade.addelement!Muscade.addin!Muscade.addin!Muscade.addnode!Muscade.allocate_drawingMuscade.colnormalizeMuscade.columnmatrixMuscade.composeMuscade.constantsMuscade.coordMuscade.describeMuscade.describeMuscade.diffed_lagrangianMuscade.diffed_residualMuscade.display_drawing!Muscade.doflistMuscade.draw!Muscade.eletypMuscade.equalMuscade.fastMuscade.findlastassignedMuscade.getdofMuscade.getndofMuscade.getresultMuscade.getsomedofsMuscade.getδtMuscade.getδωMuscade.initialize!Muscade.lagrangianMuscade.mergerequestMuscade.mod_onebasedMuscade.muscadeerrorMuscade.nosecondorderMuscade.offMuscade.positiveMuscade.prepareMuscade.print_element_arrayMuscade.residualMuscade.rowmatrixMuscade.setdof!Muscade.setscale!Muscade.solveMuscade.sparser!Muscade.studyscaleMuscade.studysingularMuscade.toggleMuscade.update_drawingMuscade.∂0Muscade.∂1Muscade.∂2Muscade.𝔉Muscade.𝔉⁻¹Muscade.𝕫log2Muscade.@espyMuscade.@espydbgMuscade.@onceMuscade.@requestMuscade.@typeof