-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathCalculateReactions.m
executable file
·170 lines (135 loc) · 4.85 KB
/
CalculateReactions.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
function [Reactions,lStar]=CalculateReactions(CtrlVar,MUA,BCs,l,options)
%%
%
% Calculates nodal reactions.
%
% Reactions=CalculateReactions(MLC,l)
%
% Nodal reactions are due to boundary conditions. They are here calculated from the values of the Lagrange parameters (l) introduced
% when enforcing Dirichlet boundary conditions.
%
% Reactions is a structure with the fields:
%
% Reactions.ubvb
% Reactions.udvd
% Reactions.h
%
% By setting the optional argument
%
% hReactionsExcludeActiveSet=true
%
%
% any positive thickness constraints that were added automatically, ie not by the user, during the run are excluded.
%
% Note that, for example, the h reactions are related to the additional mass per area required to keep the thickness at
% prescribed values. This fictitious mass flux (a_h) can be calculated as
%
% ah=Reactions.h/(F.rho*F.time)
%
% So if, for example, rho and time are in IS units, the units of the reactions are kg/m^2, and that of ah is m/yr.
%
% *Sign Convention:* Same sign convention is used as when introducing the Lagrange parameters. It follows that if, for
% example, ADDITONAL mass flux is needed to keep the thickness at a given value, the resulting thickness reactions
% (Reactions.h) are NEGATIVE. This sign convention makes sense if active constraints are identified by the sign of the
% corresponding Lagrange parameters being negative. But this sign is presumably the opposite of what one might otherwise
% expect. So if the thickness reactions are NEGATIVE, then one needs to add a POSITIVE surface mass balance equal to
%
% -Reactions.h/(F.rho*F.time)
%
% to keep the thickness at desired value.
%
%
%
% l : Lagrange variables
%
% l is one of the outputs of Ua available in DefineOutputs
%
%
% Example:
%
% To calculate and plot reactions from within DefineOutputs
%
% Reactions=CalculateReactions(CtrlVar,MUA,BCs,l);
% PlotReactions(CtrlVar,MUA,F,Reactions);
%
% Reactions are defined for all the nodes, but for nodes where no BCs have been applied,
% they will automatically be equal to zero. However, in the special case where no essential
% BCs are applied, reactions are returned as an empty matrix.
%
% If the multi-linear constraint matrix L was assembled in the FE basis, then the reactions
% are already physically correct and I only need to split them up in uv and h reactions.
%
% If L is a point-constraint matrix (default) then I need to map these into physical space
% using
%
% lambda^* = M^{-1} L' lambda
%
% This gives lambda over all nodes.
%
% To restrict it to the nodes over which the constraints were applied use:
%
% lambda^* = (L L')^{-1} L M^{-1} L' lambda
%
%
%
% Note: If the active set has only been updated, but never applied, the dimensions of the Lagrange vector (l.h) will be inconsistent with
% the number of positive thickness constraints (BCs.hFixeNode).
%
% Also: To plot reactions use:
%
% PlotReactions(CtrlVar,MUA,F,Reactions)
%
%%
arguments
CtrlVar struct
MUA struct
BCs BoundaryConditions
l struct
options.hReactionsExcludeActiveSet logical = false % this allows for h reactions to exclude those of the active thickness constraints
% only the reactions due to the user-defined thickness constraints are then calculated
end
if ~isfield(MUA,"M") || isempty(MUA.M)
MUA.M=MassMatrix2D1dof(MUA);
MUA.dM=decomposition(MUA.M,'chol','upper') ;
end
if ~isfield(MUA,"dM") || isempty(MUA.dM)
MUA.dM=decomposition(MUA.M,'chol','upper') ;
end
Reactions.ubvb=[];
Reactions.udvd=[];
Reactions.h=[];
lStar.h=[]; % only calculating physical lambdas for thickness constraints
% getting rid of all positive thickness constraints as part of the active set
if options.hReactionsExcludeActiveSet
BCs.hPosNode=[]; BCs.hPosValue=[]; lh=l.h(1:numel(BCs.hFixedNode)) ; l.h=lh ;
end
MLC=BCs2MLC(CtrlVar,MUA,BCs) ;
if ~CtrlVar.LinFEbasis
if ~isfield(MUA,'M')
MUA.M=MassMatrix2D1dof(MUA);
end
end
if ~isempty(l.ubvb)
luv=MLC.ubvbL'*l.ubvb;
try
Rx=MUA.dM\luv(1:MUA.Nnodes); % I can't see how I can know if the decomposition is in a valid state without just trying
catch
MUA.dM=decomposition(MUA.M,'chol','upper') ;
Rx=MUA.dM\luv(1:MUA.Nnodes);
end
Ry=MUA.dM\luv(MUA.Nnodes+1:end);
Reactions.ubvb=full([Rx;Ry]);
end
if ~isempty(l.udvd)
luv=MLC.udvdL'*l.udvd;
Reactions.udvd(1:MUA.Nnodes)=full(MUA.M\luv(1:MUA.Nnodes));
Reactions.udvd(MUA.Nnodes+1:end)=full(MUA.M\luv(MUA.Nnodes+1:end));
end
if ~isempty(l.h)
Lh=MLC.hL;
Reactions.h=full(MUA.dM\(Lh'*l.h));
if nargout>1
lStar.h=full((Lh*Lh')\(Lh*Reactions.h));
end
end
end