Merge lp:~fluidity-core/fluidity/iceshelf into lp:fluidity
- iceshelf
- Merge into dev-trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~fluidity-core/fluidity/iceshelf |
Merge into: | lp:fluidity |
Diff against target: |
1796 lines (+987/-706) 8 files modified
main/Fluids.F90 (+11/-16) main/Makefile.dependencies (+1/-1) parameterisation/Ice_Melt_Interface.F90 (+905/-0) parameterisation/Makefile.dependencies (+11/-10) parameterisation/Makefile.in (+1/-1) parameterisation/iceshelf_meltrate_surf_normal.F90 (+0/-678) schemas/fluidity_options.rnc (+27/-0) schemas/fluidity_options.rng (+31/-0) |
To merge this branch: | bzr merge lp:~fluidity-core/fluidity/iceshelf |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matthew Piggott | Pending | ||
Jon Hill | Pending | ||
Alexandros Avdis | Pending | ||
Adam Candy | Pending | ||
Stephan Kramer | Pending | ||
Review via email: mp+123186@code.launchpad.net |
Commit message
Description of the change
I would like to add the capability to simulate an ice shelf cavity in Fluidity-ICOM.
This code passed the buildbot (see http://
The previous merge request was rejected earlier because some codes were not necessary to model the ice shelf cavity.
Now, I have put together necessary pieces of codes to model the ice shelf cavity.
I am interested in hearing back from you all if this merge is acceptable or not.
Cheers,
Toshi
- 4053. By Satoshi Kimura
-
Merged the trunk to be updated
- 4054. By Satoshi Kimura
-
Changed the min velocity for melting
- 4055. By Satoshi Kimura
-
Changed the min velocity for melting
- 4056. By Satoshi Kimura
-
Merge the recent trunk
- 4057. By Satoshi Kimura
-
Merge the trunk
- 4058. By Satoshi Kimura
-
Merge the trunk
Unmerged revisions
- 4058. By Satoshi Kimura
-
Merge the trunk
- 4057. By Satoshi Kimura
-
Merge the trunk
- 4056. By Satoshi Kimura
-
Merge the recent trunk
- 4055. By Satoshi Kimura
-
Changed the min velocity for melting
- 4054. By Satoshi Kimura
-
Changed the min velocity for melting
- 4053. By Satoshi Kimura
-
Merged the trunk to be updated
- 4052. By Satoshi Kimura
-
Fixing the test case, iceshelf
- 4051. By Satoshi Kimura
-
Fixed my test case to pass the medium test
- 4050. By Satoshi Kimura
-
Deleted some comments in Ice_Melt_
Interface. F90 - 4049. By Satoshi Kimura
-
Added the test case
Preview Diff
1 | === modified file 'main/Fluids.F90' |
2 | --- main/Fluids.F90 2013-10-07 16:23:35 +0000 |
3 | +++ main/Fluids.F90 2013-10-25 15:24:41 +0000 |
4 | @@ -83,7 +83,7 @@ |
5 | use discrete_properties_module |
6 | use gls |
7 | use k_epsilon |
8 | - use iceshelf_meltrate_surf_normal |
9 | + use ice_melt_interface |
10 | use halos |
11 | use memory_diagnostics |
12 | use free_surface_module |
13 | @@ -401,15 +401,9 @@ |
14 | |
15 | call initialise_diagnostics(filename, state) |
16 | |
17 | - ! Initialise ice_meltrate, read constatns, allocate surface, and calculate melt rate |
18 | + ! Initialise melt interface paramerisation |
19 | if (have_option("/ocean_forcing/iceshelf_meltrate/Holland08")) then |
20 | - call melt_surf_init(state(1)) |
21 | - call melt_allocate_surface(state(1)) |
22 | - call melt_surf_calc(state(1)) |
23 | - !BC for ice melt |
24 | - if (have_option('/ocean_forcing/iceshelf_meltrate/Holland08/calculate_boundaries')) then |
25 | - call melt_bc(state(1)) |
26 | - endif |
27 | + call melt_interface_initialisation(state(1)) |
28 | end if |
29 | |
30 | ! Checkpoint at start |
31 | @@ -650,12 +644,13 @@ |
32 | end if |
33 | end if |
34 | |
35 | - ! Calculate the meltrate |
36 | - if(have_option("/ocean_forcing/iceshelf_meltrate/Holland08/") ) then |
37 | - if( (trim(field_name_list(it))=="MeltRate")) then |
38 | - call melt_surf_calc(state(1)) |
39 | + ! Calculate the (ice) interface meltrate using the parameterisation described in Holland et al. 2008 doi:10.1175/2007JCLI1909.1 |
40 | + if (have_option("/ocean_forcing/iceshelf_meltrate/Holland08")) then |
41 | + if ((trim(field_name_list(it)) == "MeltRate")) then |
42 | + call melt_interface_calculate(state(1)) |
43 | endif |
44 | - end if |
45 | + end if |
46 | + |
47 | |
48 | call get_option(trim(field_optionpath_list(it))//& |
49 | '/prognostic/equation[0]/name', & |
50 | @@ -721,9 +716,9 @@ |
51 | call gls_diffusivity(state(1)) |
52 | end if |
53 | |
54 | - !BC for ice melt |
55 | + ! Boundary conditions for the (ice) melt interface parameterisation |
56 | if (have_option('/ocean_forcing/iceshelf_meltrate/Holland08/calculate_boundaries')) then |
57 | - call melt_bc(state(1)) |
58 | + call melt_interface_boundary_condition(state(1)) |
59 | endif |
60 | |
61 | if(option_count("/material_phase/scalar_field/prognostic/spatial_discretisation/coupled_cv")>0) then |
62 | |
63 | === modified file 'main/Makefile.dependencies' |
64 | --- main/Makefile.dependencies 2013-05-31 07:04:15 +0000 |
65 | +++ main/Makefile.dependencies 2013-10-25 15:24:41 +0000 |
66 | @@ -45,7 +45,7 @@ |
67 | ../include/fldebug.mod ../include/foam_flow_module.mod \ |
68 | ../include/free_surface_module.mod ../include/global_parameters.mod \ |
69 | ../include/gls.mod ../include/goals.mod ../include/halos.mod \ |
70 | - ../include/iceshelf_meltrate_surf_normal.mod ../include/implicit_solids.mod \ |
71 | + ../include/ice_melt_interface.mod ../include/implicit_solids.mod \ |
72 | ../include/k_epsilon.mod ../include/memory_diagnostics.mod \ |
73 | ../include/meshdiagnostics.mod ../include/meshmovement.mod \ |
74 | ../include/momentum_diagnostic_fields.mod ../include/momentum_equation.mod \ |
75 | |
76 | === added file 'parameterisation/Ice_Melt_Interface.F90' |
77 | --- parameterisation/Ice_Melt_Interface.F90 1970-01-01 00:00:00 +0000 |
78 | +++ parameterisation/Ice_Melt_Interface.F90 2013-10-25 15:24:41 +0000 |
79 | @@ -0,0 +1,905 @@ |
80 | +! Copyright (C) 2006 Imperial College London and others. |
81 | +! |
82 | +! Please see the AUTHORS file in the main source directory for a full list |
83 | +! of copyright holders. |
84 | +! |
85 | +! Prof. C Pain |
86 | +! Applied Modelling and Computation Group |
87 | +! Department of Earth Science and Engineering |
88 | +! Imperial College London |
89 | +! |
90 | +! amcgsoftware@imperial.ac.uk |
91 | +! |
92 | +! This library is free software; you can redistribute it and/or |
93 | +! modify it under the terms of the GNU Lesser General Public |
94 | +! License as published by the Free Software Foundation, |
95 | +! version 2.1 of the License. |
96 | +! |
97 | +! This library is distributed in the hope that it will be useful, |
98 | +! but WITHOUT ANY WARRANTY; without even the implied arranty of |
99 | +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
100 | +! Lesser General Public License for more details. |
101 | +! |
102 | +! You should have received a copy of the GNU Lesser General Public |
103 | +! License along with this library; if not, write to the Free Software |
104 | +! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
105 | +! USA |
106 | + |
107 | +#include "fdebug.h" |
108 | + |
109 | +module ice_melt_interface |
110 | + use quadrature |
111 | + use elements |
112 | + use field_derivatives |
113 | + use fields |
114 | + use fields_base |
115 | + use field_options |
116 | + use fields_allocates |
117 | + use state_module |
118 | + use spud |
119 | + use global_parameters, only: FIELD_NAME_LEN, OPTION_PATH_LEN |
120 | + use state_fields_module |
121 | + use boundary_conditions |
122 | + use fields_manipulation |
123 | + use surface_integrals |
124 | + use fetools |
125 | + use vector_tools |
126 | + use FLDebug |
127 | + use integer_set_module |
128 | + use pickers_inquire |
129 | + use transform_elements |
130 | + use state_fields_module |
131 | + use global_parameters, only: PYTHON_FUNC_LEN |
132 | + use embed_python |
133 | +implicit none |
134 | + |
135 | + private |
136 | + integer, save :: nnodes, dimen |
137 | + type(vector_field), save :: surface_positions |
138 | + type(vector_field), save :: funky_positions |
139 | + ! Normals to the iceshelf interface surface |
140 | + type(vector_field), save :: unit_normal_vectors |
141 | + integer, dimension(:), pointer, save :: sf_nodes_point |
142 | + |
143 | + ! Fields and variables for the interface surface |
144 | + type(scalar_field), save :: ice_surfaceT, ice_surfaceS! these are used to populate the bcs |
145 | + |
146 | + public :: melt_interface_initialisation, populate_iceshelf_boundary_conditions, melt_interface_calculate, melt_interface_boundary_condition, melt_interface_cleanup, melt_interface_allocate_surface |
147 | + |
148 | +contains |
149 | + |
150 | + ! Calculation of the (ice) interface meltrate using the parameterisation described in Holland et al. 2008 doi:10.1175/2007JCLI1909.1 |
151 | + |
152 | + !---------- |
153 | + ! initialise parameters based on options |
154 | + !---------- |
155 | + |
156 | + subroutine melt_interface_initialisation(state) |
157 | + |
158 | + type(state_type), intent(inout) :: state |
159 | + type(scalar_field), pointer :: T, S |
160 | + ! For the case when Dirichlet boundary conditions are used |
161 | + character(len=FIELD_NAME_LEN) :: bc_type |
162 | + type(integer_set) :: surface_ids |
163 | + integer, dimension(:),allocatable :: interface_surface_id |
164 | + integer, dimension(2) :: shape_option |
165 | + type(mesh_type), pointer :: mesh |
166 | + type(mesh_type) :: surface_mesh |
167 | + ! Allocated and returned by create_surface_mesh |
168 | + integer, dimension(:), pointer :: surface_nodes |
169 | + integer, dimension(:), allocatable :: surface_element_list |
170 | + integer :: i,the_node |
171 | + ! For input of the hydrostatic pressure |
172 | + character(len=PYTHON_FUNC_LEN) :: subshelf_hydrostatic_pressure_function |
173 | + real :: current_time |
174 | + type(vector_field), pointer :: positions |
175 | + type(scalar_field), pointer :: subshelf_hydrostatic_pressure |
176 | + real :: c0, cI, L, TI, a, b, gammaT, gammaS, farfield_distance |
177 | + real :: T_steady, S_steady |
178 | + logical :: calculate_boundaries_T, calculate_boundaries_S |
179 | + logical :: calculate_boundary_temperature, calculate_boundary_salinity |
180 | + character(len=*), parameter :: option_path = '/ocean_forcing/iceshelf_meltrate/Holland08' |
181 | + |
182 | + ewrite(1,*) 'Melt interface initialisation begins' |
183 | + |
184 | + call melt_interface_read_coefficients(c0=c0, cI=cI, L=L, TI=TI, a=a, b=b, gammaT=gammaT, gammaS=gammaS, farfield_distance=farfield_distance, T_steady=T_steady, S_steady=S_steady) |
185 | + |
186 | + calculate_boundary_temperature=have_option(trim(option_path)//'/calculate_boundaries/bc_value_temperature') |
187 | + calculate_boundary_salinity=have_option(trim(option_path)//'/calculate_boundaries/bc_value_salinity') |
188 | + if (calculate_boundary_temperature) write(3,*) "Melt interface, initialised T_steady", T_steady |
189 | + if (calculate_boundary_salinity) write(3,*) "Melt interface, initialised S_steady", S_steady |
190 | + |
191 | + ! bc= Dirichlet initialize T and S at the ice-ocean interface |
192 | + ! This change with bc type |
193 | + if (have_option(trim(option_path)//'/calculate_boundaries')) then |
194 | + call get_option(trim(option_path)//'/calculate_boundaries', bc_type) |
195 | + select case(bc_type) |
196 | + case('neumann') |
197 | + ewrite(3,*) 'Calculating steady Neumann boundary condition - nothing to be done here.' |
198 | + case('dirichlet') |
199 | + ewrite(3,*) 'Calculating steady Dirichlet boundary condition - nothing to be done here.' |
200 | + ! Define values of temperature and salinity at ice-ocean interface |
201 | + ! Get the surface_id of the ice-ocean interface |
202 | + ! Note this code needs working through - Neumann is definitely the best choice here! |
203 | + shape_option = option_shape(trim(option_path)//"/melt_surfaceID") |
204 | + allocate(interface_surface_id(1:shape_option(1))) |
205 | + call get_option(trim(option_path)//'/melt_surfaceID', interface_surface_id) |
206 | + call allocate(surface_ids) |
207 | + call insert(surface_ids,interface_surface_id) |
208 | + mesh => extract_mesh(state,"VelocityMesh") |
209 | + ! Obtain surface_mesh, surface_element_list, from mesh and surface_id |
210 | + call melt_surf_mesh(mesh,surface_ids,surface_mesh,surface_nodes,surface_element_list) |
211 | + |
212 | + T => extract_scalar_field(state,"Temperature") |
213 | + S => extract_scalar_field(state,"Salinity") |
214 | + do i=1, size(surface_nodes) |
215 | + the_node = surface_nodes(i) |
216 | + call set(T,the_node,T_steady) |
217 | + call set(S,the_node,S_steady) |
218 | + enddo |
219 | + case default |
220 | + FLAbort('Unknown boundary type for ice-ocean interface.') |
221 | + end select |
222 | + else |
223 | + |
224 | + endif |
225 | + |
226 | + ! Read the hydrostatic pressure |
227 | + if(have_option(trim(option_path)//'/subshelf_hydrostatic_pressure')) then |
228 | + call get_option(trim(option_path)//'/subshelf_hydrostatic_pressure/python', subshelf_hydrostatic_pressure_function) |
229 | + ! Get current time |
230 | + call get_option("/timestepping/current_time", current_time) |
231 | + ! Set initial condition from python function |
232 | + |
233 | + subshelf_hydrostatic_pressure => extract_scalar_field(state,"subshelf_hydrostatic_pressure") |
234 | + positions => extract_vector_field(state,"Coordinate") |
235 | + call set_from_python_function(subshelf_hydrostatic_pressure, trim(subshelf_hydrostatic_pressure_function), positions, current_time) |
236 | + ewrite(1,*) "Melt interface initialisation, found hydrostatic pressure field" |
237 | + endif |
238 | + |
239 | + ! Additional initialisation routines |
240 | + call melt_interface_allocate_surface(state) |
241 | + call melt_interface_calculate(state) |
242 | + ! Boundary conditions for the (ice) melt interface parameterisation |
243 | + if (have_option(trim(option_path)//'/calculate_boundaries')) then |
244 | + call melt_interface_boundary_condition(state) |
245 | + endif |
246 | + |
247 | + ewrite(1,*) "Melt interface initialisation end" |
248 | + |
249 | + end subroutine melt_interface_initialisation |
250 | + |
251 | + subroutine populate_iceshelf_boundary_conditions(state) |
252 | + type(state_type), intent(in) :: state |
253 | + type(scalar_field), pointer :: T,S |
254 | + character(len=FIELD_NAME_LEN) :: bc_type |
255 | + integer, dimension(:), allocatable :: surf_id |
256 | + integer, dimension(2) :: shape_option |
257 | + type(integer_set) :: surface_ids |
258 | + !! |
259 | + type(mesh_type), pointer :: surface_mesh |
260 | + type(scalar_field) :: scalar_surface_field |
261 | + |
262 | + ewrite(1,*) "-----*** Begin iceshelf BC-----" |
263 | + ! Get vector of surface ids |
264 | + shape_option=option_shape("/ocean_forcing/iceshelf_meltrate/Holland08/melt_surfaceID") |
265 | + allocate(surf_id(1:shape_option(1))) |
266 | + call get_option("/ocean_forcing/iceshelf_meltrate/Holland08/melt_surfaceID", surf_id) |
267 | + ewrite(1,*) "surf_id", surf_id |
268 | + call get_option("/ocean_forcing/iceshelf_meltrate/Holland08/calculate_boundaries", bc_type) |
269 | + call allocate(surface_ids) |
270 | + call insert(surface_ids,surf_id) |
271 | + |
272 | + ewrite(1,*) "bc_type: ", bc_type |
273 | + ! Add boundary condition |
274 | + T => extract_scalar_field(state,"Temperature") |
275 | + S => extract_scalar_field(state,"Salinity") |
276 | + |
277 | + call add_boundary_condition(T, 'temperature_iceshelf_BC', bc_type, surf_id) |
278 | + call add_boundary_condition(S, 'salinity_iceshelf_BC', bc_type, surf_id) |
279 | + deallocate(surf_id) |
280 | + |
281 | + ! mesh of only the part of the surface where this b.c. applies for temperature |
282 | + call get_boundary_condition(T, 'temperature_iceshelf_BC', surface_mesh=surface_mesh) |
283 | + call allocate(scalar_surface_field, surface_mesh, name="value") |
284 | + call insert_surface_field(T, 'temperature_iceshelf_BC', scalar_surface_field) |
285 | + call deallocate(scalar_surface_field) |
286 | + |
287 | + ! mesh of only the part of the surface where this b.c. applies for salinity |
288 | + call get_boundary_condition(S, 'salinity_iceshelf_BC', surface_mesh=surface_mesh) |
289 | + call allocate(scalar_surface_field, surface_mesh, name="value") |
290 | + call insert_surface_field(S, 'salinity_iceshelf_BC', scalar_surface_field) |
291 | + call deallocate(scalar_surface_field) |
292 | + |
293 | + ewrite(1,*) "-----*** End iceshelf BC-----" |
294 | + end subroutine populate_iceshelf_boundary_conditions |
295 | + |
296 | + subroutine melt_interface_calculate(state) |
297 | + ! Calculate the melt rate |
298 | + |
299 | + type(state_type), intent(inout) :: state |
300 | + type(scalar_field), pointer :: Tb, Sb,MeltRate,Heat_flux,Salt_flux |
301 | + type(scalar_field), pointer :: scalarfield |
302 | + type(vector_field), pointer :: velocity,positions |
303 | + ! Debugging purpose pointer |
304 | + type(scalar_field), pointer :: T_loc,S_loc,P_loc |
305 | + type(vector_field), pointer :: V_loc,Location,Location_org |
306 | + real, dimension(:), allocatable :: vel |
307 | + integer :: i |
308 | + ! Some internal variables |
309 | + real :: speed, T,S,P,Aa,Bb,Cc,topo |
310 | + real :: c0, cI, L, TI, a, b, gammaT, gammaS, farfield_distance |
311 | + real ::loc_Tb,loc_Sb,loc_meltrate,loc_heatflux,loc_saltflux |
312 | + ! Aa*Sb^2+Bv*Sb+Cc |
313 | + ! Sink mesh part |
314 | + integer :: ele,stat,the_node |
315 | + real, dimension(:), allocatable :: local_coord,coord |
316 | + integer, dimension(:), allocatable :: surface_node_list |
317 | + type(scalar_field) :: re_pressure,re_DistanceToTop |
318 | + type(scalar_field), pointer :: temperature, salinity |
319 | + |
320 | + ewrite(1,*) "Melt interface calculation begins" |
321 | + |
322 | + call melt_interface_read_coefficients(c0=c0, cI=cI, L=L, TI=TI, a=a, b=b, gammaT=gammaT, gammaS=gammaS, farfield_distance=farfield_distance) |
323 | + |
324 | + !! All the variable under /ocean_forcing/iceshelf_meltrate/Holland08 should be in coordinate mesh |
325 | + !! coordinate mesh = continous mesh |
326 | + MeltRate => extract_scalar_field(state,"MeltRate") |
327 | + call set(MeltRate,0.0) |
328 | + Tb => extract_scalar_field(state,"Tb") |
329 | + Sb => extract_scalar_field(state,"Sb") |
330 | + |
331 | + call set(Tb,0.0) |
332 | + call set(Sb,-1.0) |
333 | + Heat_flux => extract_scalar_field(state,"Heat_flux") |
334 | + Salt_flux => extract_scalar_field(state,"Salt_flux") |
335 | + call set(Heat_flux,0.0) |
336 | + call set(Salt_flux,0.0) |
337 | + |
338 | + ! Local far field values |
339 | + T_loc => extract_scalar_field(state,"Tloc") |
340 | + S_loc => extract_scalar_field(state,"Sloc") |
341 | + P_loc => extract_scalar_field(state,"Ploc") |
342 | + V_loc => extract_vector_field(state,"Vloc") |
343 | + Location => extract_vector_field(state,"Location") |
344 | + Location_org => extract_vector_field(state,"Location_org") |
345 | + call set(T_loc,0.0) |
346 | + call set(S_loc,-1.0) |
347 | + call set(P_loc,-1.0) |
348 | + allocate(vel(V_loc%dim)) |
349 | + vel = 0.0 |
350 | + call set(V_loc,vel) |
351 | + call set(Location,vel) |
352 | + call set(Location_org,vel) |
353 | + |
354 | + positions => extract_vector_field(state,"Coordinate") |
355 | + |
356 | + ! Surface node list |
357 | + allocate(surface_node_list(size(sf_nodes_point))) |
358 | + ! sf_nodes is calculated in "melt_allocate_surface" |
359 | + surface_node_list=sf_nodes_point |
360 | + |
361 | + ! Pressure read the hydrostatic pressure, specified at schema |
362 | + scalarfield => extract_scalar_field(state,"subshelf_hydrostatic_pressure") |
363 | + call allocate(re_pressure,positions%mesh, name="RePressure") |
364 | + call remap_field(scalarfield,re_pressure,stat) |
365 | + |
366 | + if (have_option("/geometry/ocean_boundaries/scalar_field::DistanceToBottom")) then |
367 | + scalarfield => extract_scalar_field(state,"DistanceToBottom") |
368 | + call allocate(re_DistanceToTop,positions%mesh, name="ReDistanceToBottom") |
369 | + call remap_field(scalarfield,re_DistanceToTop,stat) |
370 | + endif |
371 | + |
372 | + allocate(local_coord(positions%dim+1)) |
373 | + allocate(coord(positions%dim)) |
374 | + |
375 | + temperature => extract_scalar_field(state,"Temperature") |
376 | + salinity => extract_scalar_field(state,"Salinity") |
377 | + velocity => extract_vector_field(state,"Velocity") |
378 | + |
379 | + ! Loop over the surface nodes to calculate melt rate |
380 | + do i=1,size(surface_node_list) |
381 | + the_node = surface_node_list(i) |
382 | + ! Interpolating |
383 | + coord = node_val(funky_positions,the_node) |
384 | + call picker_inquire(positions, coord, ele, local_coord,global=.false.) |
385 | + |
386 | + !! we know that this coord (funky position) does not exist in the domain. |
387 | + if (sum(local_coord) .gt. 2.0) then |
388 | + ewrite(0,*) "Melt interface, funky coordinate: ", node_val(funky_positions,the_node) |
389 | + !! node_val(surface_positions,the_node) = node_val(positions,the_node) |
390 | + ewrite(0,*) "Melt interface, original element: ",ele |
391 | + ewrite(0,*) "Melt interface, sum of local_coord: ", sum(local_coord) |
392 | + FLExit("Melt interface, your funky_positions is out of the domain. Change melt_LayerLength.") |
393 | + endif |
394 | + |
395 | + !Number of nodes per element for temperature |
396 | + ! Find T at a particular element given the field,element, |
397 | + !INPUT: field, element number |
398 | + !Output: real value |
399 | + |
400 | + call scalar_finder_ele(temperature,ele,positions%dim+1,local_coord,T) |
401 | + call scalar_finder_ele(salinity,ele,positions%dim+1,local_coord,S) |
402 | + call vector_finder_ele(velocity,ele,positions%dim+1,local_coord,vel) |
403 | + |
404 | + ! Pressure from the schema |
405 | + P = node_val(re_pressure,the_node) |
406 | + speed = sqrt(sum(vel**2)) |
407 | + |
408 | + if (speed .lt. 0.0001) then |
409 | + speed = 0.0001 |
410 | + |
411 | + endif |
412 | + ! constant = -7.53e-8 [C Pa^(-1)] comes from Holland and Jenkins Table 1 |
413 | + topo = -7.53e-8*P |
414 | + |
415 | + ! Define Aa,Bb,Cc |
416 | + ! Aa*Sb**2 + Bb*Sb + Cc = 0.0 |
417 | + Aa = -gammaS * speed * cI * a + a * c0 * gammaT * speed |
418 | + |
419 | + Bb = -gammaS * speed * L + gammaS * speed * S * cI * a |
420 | + Bb = Bb - gammaS * speed * cI * (b + topo) + gammaS * speed * cI * TI |
421 | + Bb = Bb - c0 * gammaT * speed * T + c0 * gammaT * speed * (b + topo) |
422 | + |
423 | + Cc = gammaS * speed * S * L + gammaS * speed * S * cI * (b + topo) + gammaS * speed * S * (-cI * TI) |
424 | + |
425 | + ! This could be a linear equation if Aa=0 |
426 | + if (Aa .eq. 0.0) then |
427 | + loc_Sb = -Cc/Bb |
428 | + else |
429 | + ! Calculate for the 2nd oewrite(1,*) "size(surface_element_list)"rder polynomial. |
430 | + ! We have two solutions. |
431 | + loc_Sb = (-Bb + sqrt(Bb**2 - 4.0*Aa*Cc))/(2.0*Aa) |
432 | + ! loc_Sb has to be larger than 0; since the salinity in the ocean is positive definite. |
433 | + if (loc_Sb .lt. 0.0) then |
434 | + loc_Sb = (-Bb - sqrt(Bb**2 - 4.0*Aa*Cc))/(2.0*Aa) |
435 | + endif |
436 | + if (loc_Sb .lt. 0.0) then |
437 | + ewrite(0,*) "Melt interface, loc_Sb: ", loc_Sb |
438 | + ewrite(0,*) "Melt interface, Aa: ", Aa |
439 | + ewrite(0,*) "Melt interface, Bb: ", Bb |
440 | + ewrite(0,*) "Melt interface, Cc: ", Cc |
441 | + ewrite(0,*) "Melt interface, T: ", T |
442 | + ewrite(0,*) "Melt interface, S: ", S |
443 | + ewrite(0,*) "Melt interface, P: ", P |
444 | + ewrite(0,*) "Melt interface, speed: ", speed |
445 | + FLExit("Melt interface, Sb is negative. The range of Salinity is not right.") |
446 | + endif |
447 | + endif |
448 | + |
449 | + loc_Tb = a*loc_Sb + b + topo |
450 | + loc_meltrate = gammaS*speed*(S-loc_Sb)/loc_Sb |
451 | + !! Heat flux to the ocean |
452 | + loc_heatflux = (gammaT*speed+ loc_meltrate)*(loc_Tb - T) |
453 | + !! Salt flux to the ocean |
454 | + loc_saltflux = (gammaS*speed+loc_meltrate)*(loc_Sb - S) |
455 | + |
456 | + !! These are needed to implement BCs. |
457 | + call set(MeltRate, the_node, loc_meltrate) |
458 | + call set(Tb, the_node, loc_Tb) |
459 | + call set(Sb, the_node, loc_Sb) |
460 | + call set(Heat_flux, the_node,loc_heatflux) |
461 | + call set(Salt_flux, the_node,loc_saltflux) |
462 | + |
463 | + !!Far field values |
464 | + call set(T_loc,the_node,T) |
465 | + call set(S_loc,the_node,S) |
466 | + call set(P_loc,the_node,P) |
467 | + call set(V_loc,the_node,vel) |
468 | + call set(Location,the_node,node_val(funky_positions,the_node)) |
469 | + call set(Location_org,the_node,node_val(positions,the_node)) |
470 | + |
471 | + enddo |
472 | + |
473 | + deallocate(local_coord) |
474 | + deallocate(coord) |
475 | + call deallocate(re_pressure) |
476 | + |
477 | + if (have_option("/geometry/ocean_boundaries/scalar_field::DistanceToBottom")) then |
478 | + call deallocate(re_DistanceToTop) |
479 | + endif |
480 | + |
481 | + ! Remap meltrate_p heat_flux_p salt_flux_p onto MeltRate Heat_flux Salt_flux |
482 | + ! Mappting continous mesh to discontinous mesh |
483 | + |
484 | + ewrite(1,*) "Melt interface calculation end" |
485 | + |
486 | + end subroutine melt_interface_calculate |
487 | + |
488 | + subroutine melt_interface_boundary_condition(state) |
489 | + ! See preprocessor/Boundary_Conditions_From_options.F90 populate_iceshelf_boundary_conditions(states(1)) as well |
490 | + type(state_type), intent(inout) :: state |
491 | + ! Boundary conditions |
492 | + type(scalar_field), pointer :: TT,SS |
493 | + type(scalar_field), pointer :: scalar_surface, scalar_surface2 |
494 | + type(mesh_type), pointer :: ice_mesh |
495 | + character(len=FIELD_NAME_LEN) :: bc_type |
496 | + type(scalar_field) :: T_bc,S_bc |
497 | + type(scalar_field), pointer :: Tflux,Sflux |
498 | + type(scalar_field), pointer :: Tb,Sb |
499 | + integer :: i, the_node |
500 | + real :: Tz,Sz |
501 | + type(mesh_type), pointer :: mesh |
502 | + type(mesh_type) :: surface_mesh |
503 | + integer, dimension(:), pointer :: surface_nodes ! allocated and returned by create_surface_mesh |
504 | + integer, dimension(:), allocatable :: surface_element_list |
505 | + type(integer_set) :: surface_ids |
506 | + integer, dimension(:),allocatable :: surf_id |
507 | + integer, dimension(2) :: shape_option |
508 | + type(vector_field) :: unit_normal_vectors_vel |
509 | + type(scalar_field) :: heat_flux_vel,salt_flux_vel |
510 | + type(vector_field), pointer :: velocity |
511 | + integer :: stat |
512 | + real, dimension(:), allocatable :: vel |
513 | + real :: T_steady, S_steady |
514 | + logical :: calculate_boundary_temperature, calculate_boundary_salinity |
515 | + character(len=*), parameter :: option_path = '/ocean_forcing/iceshelf_meltrate/Holland08' |
516 | + character(len=*), parameter :: option_path_bc = '/ocean_forcing/iceshelf_meltrate/Holland08/calculate_boundaries' |
517 | + |
518 | + ewrite(1,*) "Melt interface boundary condition begins" |
519 | + call melt_interface_read_coefficients(T_steady=T_steady, S_steady=S_steady) |
520 | + calculate_boundary_temperature=have_option(trim(option_path)//'/calculate_boundaries/bc_value_temperature') |
521 | + calculate_boundary_salinity=have_option(trim(option_path)//'/calculate_boundaries/bc_value_salinity') |
522 | + |
523 | +!! See ./preprocessor/Boundary_Conditions_From_options.F90 populate_iceshelf_boundary_conditions(states(1)) as well |
524 | + ! Get the surface_id of the ice-ocean interface |
525 | + shape_option=option_shape(trim(option_path)//"/melt_surfaceID") |
526 | + allocate(surf_id(1:shape_option(1))) |
527 | + call get_option(trim(option_path)//'/melt_surfaceID',surf_id) |
528 | + call allocate(surface_ids) |
529 | + call insert(surface_ids,surf_id) |
530 | + |
531 | + TT=> extract_scalar_field(state,"Temperature") |
532 | + SS=> extract_scalar_field(state,"Salinity") |
533 | + velocity => extract_vector_field(state,"Velocity") |
534 | + |
535 | + if (node_count(TT) .eq. node_count(velocity)) then |
536 | + mesh => extract_mesh(state,"VelocityMesh") |
537 | + else |
538 | + mesh => extract_mesh(state,"CoordinateMesh") |
539 | + endif |
540 | + call melt_surf_mesh(mesh,surface_ids,surface_mesh,surface_nodes,surface_element_list) |
541 | + |
542 | +!! Remapt the contious mesh to discon, unit_normal vecotr |
543 | + |
544 | + call allocate(unit_normal_vectors_vel,velocity%dim,TT%mesh,"MyVelocitySurfaceMesh") |
545 | + |
546 | + allocate(vel(velocity%dim)) |
547 | + vel = 0.0 |
548 | + call set(unit_normal_vectors_vel,vel) |
549 | + deallocate(vel) |
550 | + |
551 | + call remap_field(unit_normal_vectors,unit_normal_vectors_vel,stat) |
552 | + |
553 | + call allocate(T_bc,TT%mesh, name="T_boundary") |
554 | + call allocate(S_bc,SS%mesh, name="S_boundary") |
555 | + |
556 | + ! Surface node list |
557 | + ! This change with bc type |
558 | + call get_option(trim(option_path_bc), bc_type) |
559 | + |
560 | + select case(bc_type) |
561 | + case("neumann") |
562 | + Tflux => extract_scalar_field(state,"Heat_flux") |
563 | + Sflux => extract_scalar_field(state,"Salt_flux") |
564 | + |
565 | + !! Remap the heat flux |
566 | + call allocate(heat_flux_vel,TT%mesh,"MyHeatFluxSurfaceMesh") |
567 | + call set(heat_flux_vel,0.0) |
568 | + call remap_field(Tflux,heat_flux_vel,stat) |
569 | + |
570 | + !! Remap the salt flux |
571 | + call allocate(salt_flux_vel,SS%mesh,"MySaltFluxSurfaceMesh") |
572 | + call set(salt_flux_vel,0.0) |
573 | + call remap_field(Sflux,salt_flux_vel,stat) |
574 | + |
575 | + ! create a surface mesh to place values onto. This is for the top surface |
576 | + call get_boundary_condition(TT, 'temperature_iceshelf_BC', surface_mesh=ice_mesh) |
577 | + call allocate(ice_surfaceT, ice_mesh, name="ice_surfaceT") |
578 | + !! Temperature |
579 | + scalar_surface => extract_surface_field(TT, 'temperature_iceshelf_BC', "value") |
580 | + |
581 | + do i=1,node_count(ice_surfaceT) |
582 | + the_node = surface_nodes(i) |
583 | + Tz = node_val(heat_flux_vel,the_node) |
584 | + call set(scalar_surface,i,Tz) |
585 | + enddo |
586 | + |
587 | + ! Salinity |
588 | + call get_boundary_condition(SS, 'salinity_iceshelf_BC', surface_mesh=ice_mesh) |
589 | + call allocate(ice_surfaceS, ice_mesh, name="ice_surfaceS") |
590 | + !! Salinity |
591 | + scalar_surface2 => extract_surface_field(SS, 'salinity_iceshelf_BC', "value") |
592 | + do i=1,node_count(ice_surfaceS) |
593 | + the_node = surface_nodes(i) |
594 | + Sz = node_val(salt_flux_vel,the_node) |
595 | + call set(scalar_surface2,i,Sz) |
596 | + enddo |
597 | + ! Deallocate the heat_flux and salt_flux on velocity mesh |
598 | + call deallocate(heat_flux_vel) |
599 | + call deallocate(salt_flux_vel) |
600 | + |
601 | + ! If the fluxes were constant |
602 | + if (calculate_boundary_temperature) then |
603 | + call set(T_bc,T_steady) |
604 | + ! create a surface mesh to place values onto. This is for the top surface |
605 | + call get_boundary_condition(TT, 'temperature_iceshelf_BC', surface_mesh=ice_mesh) |
606 | + call allocate(ice_surfaceT, ice_mesh, name="ice_surfaceT") |
607 | + do i=1,node_count(ice_surfaceT) |
608 | + the_node = surface_nodes(i) |
609 | + call set(ice_surfaceT,i,node_val(T_bc,the_node)) |
610 | + enddo |
611 | + ! Temperature |
612 | + scalar_surface => extract_surface_field(TT, 'temperature_iceshelf_BC', "value") |
613 | + call remap_field(ice_surfaceT, scalar_surface) |
614 | + endif |
615 | + |
616 | + if (have_option(trim(option_path_bc)//'/bc_value_salinity')) then |
617 | + call set(S_bc,S_steady) |
618 | + ! Salinity |
619 | + call get_boundary_condition(SS, 'salinity_iceshelf_BC', surface_mesh=ice_mesh) |
620 | + call allocate(ice_surfaceS, ice_mesh, name="ice_surfaceS") |
621 | + do i=1,node_count(ice_surfaceS) |
622 | + the_node = surface_nodes(i) |
623 | + call set(ice_surfaceS,i,node_val(S_bc,the_node)) |
624 | + enddo |
625 | + !! Salinity |
626 | + scalar_surface => extract_surface_field(SS, 'salinity_iceshelf_BC', "value") |
627 | + call remap_field(ice_surfaceS, scalar_surface) |
628 | + endif |
629 | + |
630 | + case("dirichlet") |
631 | + Tb => extract_scalar_field(state,"Tb") |
632 | + Sb => extract_scalar_field(state,"Sb") |
633 | + do i=1,node_count(T_bc) |
634 | + call set(T_bc,i,node_val(Tb,i)) |
635 | + call set(S_bc,i,node_val(Sb,i)) |
636 | + enddo |
637 | + ! When testing BC implementation |
638 | + if (calculate_boundary_temperature) then |
639 | + call set(T_bc,T_steady) |
640 | + ewrite(3,*) "Melt interface, initialised T_steady", T_steady |
641 | + endif |
642 | + if (calculate_boundary_salinity) then |
643 | + call set(S_bc,S_steady) |
644 | + ewrite(3,*) "Melt interface, initialised S_steady", S_steady |
645 | + endif |
646 | + |
647 | + case default |
648 | + FLAbort('Unknown boundary condition for ice-ocean interface') |
649 | + end select |
650 | + |
651 | + call deallocate(T_bc) |
652 | + call deallocate(S_bc) |
653 | + call deallocate(ice_surfaceT) |
654 | + call deallocate(ice_surfaceS) |
655 | + call deallocate(unit_normal_vectors_vel) |
656 | + call deallocate(surface_mesh) |
657 | + |
658 | + ewrite(1,*) "Melt interface boundary condition end" |
659 | + |
660 | + end subroutine melt_interface_boundary_condition |
661 | + |
662 | + |
663 | + subroutine melt_interface_cleanup() |
664 | + ewrite(1,*) "Melt interface, cleaning up melt variables" |
665 | + call deallocate(surface_positions) |
666 | + call deallocate(funky_positions) |
667 | + call deallocate(unit_normal_vectors) |
668 | + |
669 | + deallocate(sf_nodes_point) |
670 | + end subroutine melt_interface_cleanup |
671 | + |
672 | + |
673 | + !------------------------------------------------------------------! |
674 | + ! Private subroutines ! |
675 | + !------------------------------------------------------------------! |
676 | + |
677 | + subroutine melt_interface_allocate_surface(state) |
678 | + type(state_type), intent(inout) :: state |
679 | + type(vector_field), pointer :: positions |
680 | + type(mesh_type), pointer :: mesh |
681 | + type(mesh_type) :: surface_mesh |
682 | + ! Allocated and returned by create_surface_mesh |
683 | + integer, dimension(:), pointer :: surface_nodes |
684 | + integer, dimension(:), allocatable :: surface_element_list |
685 | + integer :: face,i,j,k |
686 | + real, dimension(:), allocatable :: coord |
687 | + ! For transform_facet_to_physical |
688 | + real, dimension(:,:), allocatable :: normal |
689 | + real, dimension(:), allocatable :: av_normal !Average of normal |
690 | + type(element_type), pointer :: x_shape_f |
691 | + real, dimension(:), allocatable :: xyz !New location of surface_mesh, farfield_distance away from the boundary |
692 | + type(integer_set) :: surface_ids |
693 | + integer, dimension(:),allocatable :: interface_surface_id |
694 | + |
695 | + ! For the vector averaging schem, taking the area of the surface element etc |
696 | + real, dimension(:,:), allocatable :: table |
697 | + integer, dimension(:,:), allocatable :: node_occupants |
698 | + integer :: st,en,node,dim_vec |
699 | + real :: area_sum |
700 | + integer, dimension(2) :: shape_option |
701 | + real, dimension(:), allocatable :: local_coord |
702 | + integer :: ele, counter,Nit |
703 | + real, dimension(:), allocatable :: vel |
704 | + real :: c0, cI, L, TI, a, b, gammaT, gammaS, farfield_distance |
705 | + character(len=*), parameter :: option_path = '/ocean_forcing/iceshelf_meltrate/Holland08/melt_surfaceID' |
706 | + |
707 | + ewrite(1,*) "Melt interface allocation of surface parameters" |
708 | + |
709 | + call melt_interface_read_coefficients(c0=c0, cI=cI, L=L, TI=TI, a=a, b=b, gammaT=gammaT, gammaS=gammaS, farfield_distance=farfield_distance) |
710 | + |
711 | + ! Get the surface_id of the ice-ocean interface |
712 | + shape_option=option_shape(trim(option_path)) |
713 | + allocate(interface_surface_id(1:shape_option(1))) |
714 | + call get_option(trim(option_path), interface_surface_id) |
715 | + call allocate(surface_ids) |
716 | + call insert(surface_ids,interface_surface_id) |
717 | + |
718 | + mesh => extract_mesh(state,"CoordinateMesh") |
719 | + ! Input, mesh, surface_id |
720 | + ! Output surface_mesh, surface_element_list |
721 | + call melt_surf_mesh(mesh, surface_ids, surface_mesh, surface_nodes, surface_element_list) |
722 | + |
723 | + allocate(sf_nodes_point(size(surface_nodes))) |
724 | + sf_nodes_point = surface_nodes |
725 | + positions => extract_vector_field(state,"Coordinate") |
726 | + ! Sink the surface_mesh to the 'far field' |
727 | + call allocate(surface_positions,positions%dim,mesh,"MySurfacePosition") |
728 | + call allocate(funky_positions,surface_positions%dim, surface_positions%mesh,"MyFunkyPosition") |
729 | + call allocate(unit_normal_vectors,surface_positions%dim, surface_positions%mesh,"MyFunkyUnitVec") |
730 | + allocate(vel(positions%dim)) |
731 | + vel = 0.0 |
732 | + call set(unit_normal_vectors,vel) |
733 | + deallocate(vel) |
734 | + ! Check above |
735 | + |
736 | + ! Remap the positions vector to the surface mesh, surface_positions |
737 | + call remap_field_to_surface(positions, surface_positions, surface_element_list) |
738 | + |
739 | + ! Loop over # of surface elements |
740 | + !nf = size(surface_element_list) |
741 | + !2 comes because there are 2 nodes per a surface_element (assumption!) |
742 | + ! this number could be three for 3D problem, room for change |
743 | + ! dim_vec is the dimension of the positions, either 2 or 3. |
744 | + ! node_occupants(1,1:dim_vec*nf) = nodes that occupies the surface elements |
745 | + ! node_occupants(2,:) = surface elements |
746 | + ! table(1,:) = area of the face |
747 | + ! table(2,:) = normal_x |
748 | + ! table(3,:) = normal_y |
749 | + ! table(4,:) = normal_z |
750 | + dim_vec = positions%dim |
751 | + allocate(coord(dim_vec)) |
752 | + allocate(node_occupants(2,dim_vec*size(surface_element_list))) |
753 | + allocate(table(dim_vec+1,dim_vec*size(surface_element_list))) |
754 | + allocate(av_normal(dim_vec)) |
755 | + allocate(xyz(dim_vec)) |
756 | + allocate(local_coord(positions%dim+1)) |
757 | + |
758 | + do i=1,size(surface_element_list) |
759 | + st = 1+dim_vec*(i-1) |
760 | + en = dim_vec+dim_vec*(i-1) |
761 | + face = surface_element_list(i) |
762 | + node_occupants(2,st:en) = face |
763 | + node_occupants(1,st:en) = face_global_nodes(positions, face) |
764 | + ! Calculate the area of the surface element |
765 | + ! For 2D, the area is the length |
766 | + if (dim_vec .eq. 2) then |
767 | + table(1,st:en) = calc_area2(positions,node_occupants(1,st:en)) |
768 | + endif |
769 | + |
770 | + ! For 3D, the area become the area of the triangle (assumption here). |
771 | + ! Subroutine calc_area3 uses Heron's formula. |
772 | + if (dim_vec .eq. 3) then |
773 | + table(1,st:en) = calc_area3(positions,node_occupants(1,st:en)) |
774 | + endif |
775 | + ! Compute the normal vector at the surface element. |
776 | + x_shape_f=>face_shape(positions,face) |
777 | + allocate(normal(dim_vec,x_shape_f%ngi)) !(dim x x_shape_f%ngi) |
778 | + call transform_facet_to_physical(positions, face, normal=normal) |
779 | + av_normal = sum(normal,2) |
780 | + !"normal" should be the same; since the normal vector on the quadrature point does not change. |
781 | + av_normal = av_normal/(sum(av_normal*av_normal))**(0.5) ! normalize the vector |
782 | + deallocate(normal) |
783 | + ! Since av_normal is outward to the boundary, we will put -sign. We want the vector into the boundary |
784 | + av_normal = -av_normal |
785 | + ! Store av_normal, the normal vector averaged over quadrature points, in table |
786 | + do j=1,dim_vec |
787 | + table(j+1,st:en)=av_normal(j) |
788 | + enddo |
789 | + enddo |
790 | + |
791 | + |
792 | + do i=1,size(node_occupants(1,:)) |
793 | + node = node_occupants(1,i) |
794 | + av_normal(:) = 0.0 |
795 | + area_sum = 0.0 |
796 | + ! This loop average the normal vector based on the areas of surface elements |
797 | + ! which share the "node". Using hash table may speed up this process |
798 | + do j=1,size(node_occupants(1,:)) |
799 | + !Pick the surface elements that sheare the "node" |
800 | + if (node_occupants(1,j) .eq. node) then |
801 | + do k=1,dim_vec |
802 | + |
803 | + av_normal(k) = av_normal(k) + table(k+1,j)*table(1,j) |
804 | + enddo |
805 | + !The total areas of the surface elements that occupies the "node" |
806 | + area_sum = area_sum + table(1,j) |
807 | + endif |
808 | + enddo |
809 | + |
810 | + av_normal = av_normal / area_sum |
811 | + ! normalize |
812 | + av_normal = av_normal/(sum(av_normal*av_normal))**(0.5) |
813 | + |
814 | + farfield_distance = abs(farfield_distance) |
815 | + ! Shift the location of the surface nodes. |
816 | + !The coordinate of the surface node. |
817 | + |
818 | + coord = node_val(positions,node) |
819 | + ! farfield_distance = ||xyz - coord|| xyz and coord are vectors |
820 | + xyz = av_normal*farfield_distance + coord |
821 | + |
822 | +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
823 | + ! have options /ocean_forcing/iceshelf_meltrate/Holland08/melt_LayerRelax |
824 | + if (have_option("/ocean_forcing/iceshelf_meltrate/Holland08/melt_LayerRelax")) then |
825 | + call get_option('/ocean_forcing/iceshelf_meltrate/Holland08/melt_LayerRelax/N',Nit) |
826 | + !!Check if xyz is within the domain |
827 | + call picker_inquire(positions, xyz, ele, local_coord,global=.false.) |
828 | + !! If sum(local_coord) is not equal to 1, |
829 | + !! we know that this coord (funky position) does not exist in the domain. |
830 | + |
831 | + counter = 1 |
832 | + do while (sum(local_coord) .gt. 2.0 .and. counter .lt. Nit) |
833 | + xyz = av_normal*(farfield_distance-counter*(farfield_distance/Nit)) + coord |
834 | + call picker_inquire(positions, xyz, ele, local_coord,global=.false.) |
835 | + counter = counter+1 |
836 | + enddo |
837 | + |
838 | + if (sum(local_coord) .gt. 2.0) then |
839 | + ewrite(1,*) "icehslef location, coord: ", coord |
840 | + ewrite(1,*) "funky position, xyz: ", xyz |
841 | + call picker_inquire(positions, coord, ele, local_coord,global=.false.) |
842 | + ewrite(1,*) "Original ele: ",ele |
843 | + ewrite(1,*) "sum of local_coord: ", sum(local_coord) |
844 | + FLExit("In setting funky_position, your funky_positions is out of the domain. Change melt_LayerLength.") |
845 | + endif |
846 | + endif |
847 | +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
848 | + |
849 | + call set(funky_positions,node,xyz) ! Set the coordinate of sinked nodes, funky positions. |
850 | + call set(surface_positions,node,coord) !Original coordinate of the surface |
851 | + call set(unit_normal_vectors,node,av_normal) !save the unit normal vector for Kt and Ks calculation |
852 | + |
853 | + node = 0 |
854 | + enddo |
855 | + |
856 | + ! Now deallocate junk |
857 | + deallocate(coord) |
858 | + deallocate(table) |
859 | + deallocate(node_occupants) |
860 | + deallocate(av_normal) |
861 | + deallocate(xyz) |
862 | + deallocate(local_coord) |
863 | + call deallocate(surface_ids) |
864 | + call deallocate(surface_mesh) |
865 | + ewrite(1,*) "Melt interface allocation of surface parameters end" |
866 | + |
867 | + end subroutine melt_interface_allocate_surface |
868 | + |
869 | + subroutine melt_surf_mesh(mesh,surface_ids,surface_mesh,surface_nodes,surface_element_list) |
870 | + |
871 | + type(mesh_type), intent(in) :: mesh |
872 | + type(integer_set), intent(in) :: surface_ids |
873 | + type(mesh_type), intent(out) :: surface_mesh |
874 | + integer, dimension(:), pointer, intent(out) :: surface_nodes ! allocated and returned by create_surface_mesh |
875 | + integer, dimension(:), allocatable, intent(out) :: surface_element_list |
876 | + ! integer, dimension(:), allocatable :: surface_nodes_out |
877 | + type(integer_set) :: surface_elements |
878 | + integer :: i |
879 | + ! create a set of surface elements that have surface id in 'surface_ids' |
880 | + |
881 | + call allocate(surface_elements) |
882 | + do i=1, surface_element_count(mesh) |
883 | + if (has_value(surface_ids, surface_element_id(mesh, i))) then |
884 | + call insert(surface_elements, i) |
885 | + end if |
886 | + end do |
887 | + |
888 | + allocate(surface_element_list(key_count(surface_elements))) |
889 | + surface_element_list=set2vector(surface_elements) |
890 | + call create_surface_mesh(surface_mesh, surface_nodes, mesh, surface_element_list, name=trim(mesh%name)//"ToshisMesh") |
891 | + end subroutine melt_surf_mesh |
892 | + |
893 | + subroutine melt_interface_read_coefficients(c0, cI, L, TI, a, b, gammaT, gammaS, farfield_distance, T_steady, S_steady) |
894 | + real, intent(out), optional :: c0, cI, L, TI, a, b, gammaT, gammaS, farfield_distance, T_steady, S_steady |
895 | + real :: Cd |
896 | + character(len=*), parameter :: option_path = '/ocean_forcing/iceshelf_meltrate/Holland08' |
897 | + |
898 | + ! Get the 6 model constants |
899 | + if (present(c0)) call get_option(trim(option_path)//'c0', c0, default = 3974.0) |
900 | + if (present(cI)) call get_option(trim(option_path)//'cI', cI, default = 2009.0) |
901 | + if (present(L)) call get_option(trim(option_path)//'/L', L, default = 3.35e5) |
902 | + if (present(TI)) call get_option(trim(option_path)//'/TI', TI, default = -25.0) |
903 | + if (present(a)) call get_option(trim(option_path)//'/a', a, default = -0.0573) |
904 | + if (present(b)) call get_option(trim(option_path)//'/b', b, default = 0.0832) |
905 | + if (present(farfield_distance)) call get_option(trim(option_path)//'/melt_LayerLength', farfield_distance) |
906 | + |
907 | + if (present(gammaT).or.present(gammaS)) call get_option(trim(option_path)//'/Cd', Cd, default = 1.5e-3) |
908 | + if (present(gammaT)) gammaT = sqrt(Cd)/(12.5*(7.0**(2.0/3.0))-9.0) |
909 | + if (present(gammaS)) gammaS = sqrt(Cd)/(12.5*(700.0**(2.0/3.0))-9.0) |
910 | + |
911 | + ! When steady boundary options are enabled |
912 | + if (present(T_steady)) call get_option(trim(option_path)//'/calculate_boundaries/bc_value_temperature',T_steady, default = 0.0) |
913 | + if (present(S_steady)) call get_option(trim(option_path)//'/calculate_boundaries/bc_value_salinity',S_steady, default = 34.0) |
914 | + |
915 | + end subroutine melt_interface_read_coefficients |
916 | + |
917 | + subroutine scalar_finder_ele(scalar,ele,element_dim,local_coord,scalar_out) |
918 | + type(scalar_field), pointer, intent(in) :: scalar |
919 | + integer, intent(in) :: ele |
920 | + integer, intent(in) :: element_dim |
921 | + real, dimension(element_dim), intent(in) :: local_coord |
922 | + real, intent(out) :: scalar_out |
923 | + integer :: j,node |
924 | + integer, dimension(:), allocatable :: node_lists |
925 | + |
926 | + allocate(node_lists(size(ele_nodes(scalar,ele)))) |
927 | + node_lists = ele_nodes(scalar,ele) !Lists of nodes that occupies the element. |
928 | + scalar_out = 0.0 |
929 | + do j=1,size(node_lists) |
930 | + node = node_lists(j) |
931 | + scalar_out = scalar_out + node_val(scalar,node)*local_coord(j) |
932 | + enddo |
933 | + end subroutine scalar_finder_ele |
934 | + |
935 | + subroutine vector_finder_ele(vector,ele,element_dim,local_coord,vector_out) |
936 | + type(vector_field), pointer, intent(in) :: vector |
937 | + integer, intent(in) :: ele |
938 | + integer, intent(in) :: element_dim |
939 | + real, dimension(element_dim), intent(in) :: local_coord |
940 | + real, dimension(element_dim-1), intent(out) :: vector_out |
941 | + integer :: j,node |
942 | + integer, dimension(:), allocatable :: node_lists |
943 | + |
944 | + allocate(node_lists(size(ele_nodes(vector,ele)))) |
945 | + |
946 | + node_lists = ele_nodes(vector,ele) !Lists of nodes that occupies the element. |
947 | + vector_out(:) = 0.0 |
948 | + do j=1,size(node_lists) |
949 | + node = node_lists(j) |
950 | + vector_out = vector_out + node_val(vector,node)*local_coord(j) |
951 | + enddo |
952 | + end subroutine vector_finder_ele |
953 | + |
954 | + real function setnan(arg) |
955 | + real :: arg |
956 | + setnan = sqrt(arg) |
957 | + end function |
958 | + |
959 | + real function calc_area2(positions,nodes) |
960 | + type(vector_field), pointer :: positions |
961 | + integer, dimension(2) :: nodes |
962 | + real, dimension(2) :: coord1,coord2 |
963 | + coord1 = node_val(positions,nodes(1)) |
964 | + coord2 = node_val(positions,nodes(2)) |
965 | + calc_area2 = (sum((coord2 - coord1)**2))**0.5 |
966 | + end function |
967 | + |
968 | + real function calc_area3(positions,nodes) |
969 | + type(vector_field), pointer :: positions |
970 | + integer, dimension(3) :: nodes |
971 | + real, dimension(3) :: coord1,coord2,coord3 |
972 | + real :: a,b,c,s |
973 | + coord1 = node_val(positions,nodes(1)) |
974 | + coord2 = node_val(positions,nodes(2)) |
975 | + coord3 = node_val(positions,nodes(3)) |
976 | + ! Use Heron's formula to calculate the area of triangle |
977 | + a = (sum((coord2 - coord1)**2))**0.5 |
978 | + b = (sum((coord3 - coord1)**2))**0.5 |
979 | + c = (sum((coord2 - coord3)**2))**0.5 |
980 | + s = 0.5*(a+b+c) |
981 | + calc_area3 = (s*(s-a)*(s-b)*(s-c))**0.5 |
982 | + end function |
983 | + |
984 | +end module ice_melt_interface |
985 | |
986 | === modified file 'parameterisation/Makefile.dependencies' |
987 | --- parameterisation/Makefile.dependencies 2013-02-25 18:41:05 +0000 |
988 | +++ parameterisation/Makefile.dependencies 2013-10-25 15:24:41 +0000 |
989 | @@ -21,20 +21,21 @@ |
990 | ../include/state_fields_module.mod ../include/state_module.mod \ |
991 | ../include/vertical_extrapolation_module.mod |
992 | |
993 | -../include/iceshelf_meltrate_surf_normal.mod: iceshelf_meltrate_surf_normal.o |
994 | +../include/ice_melt_interface.mod: Ice_Melt_Interface.o |
995 | @true |
996 | |
997 | -iceshelf_meltrate_surf_normal.o ../include/iceshelf_meltrate_surf_normal.mod: \ |
998 | - iceshelf_meltrate_surf_normal.F90 ../include/boundary_conditions.mod \ |
999 | - ../include/elements.mod ../include/fdebug.h ../include/fetools.mod \ |
1000 | +Ice_Melt_Interface.o ../include/ice_melt_interface.mod: Ice_Melt_Interface.F90 \ |
1001 | + ../include/boundary_conditions.mod ../include/elements.mod \ |
1002 | + ../include/embed_python.mod ../include/fdebug.h ../include/fetools.mod \ |
1003 | ../include/field_derivatives.mod ../include/field_options.mod \ |
1004 | ../include/fields.mod ../include/fields_allocates.mod \ |
1005 | - ../include/fields_manipulation.mod ../include/fldebug.mod \ |
1006 | - ../include/global_parameters.mod ../include/integer_set_module.mod \ |
1007 | - ../include/pickers_inquire.mod ../include/quadrature.mod \ |
1008 | - ../include/spud.mod ../include/state_fields_module.mod \ |
1009 | - ../include/state_module.mod ../include/surface_integrals.mod \ |
1010 | - ../include/transform_elements.mod ../include/vector_tools.mod |
1011 | + ../include/fields_base.mod ../include/fields_manipulation.mod \ |
1012 | + ../include/fldebug.mod ../include/global_parameters.mod \ |
1013 | + ../include/integer_set_module.mod ../include/pickers_inquire.mod \ |
1014 | + ../include/quadrature.mod ../include/spud.mod \ |
1015 | + ../include/state_fields_module.mod ../include/state_module.mod \ |
1016 | + ../include/surface_integrals.mod ../include/transform_elements.mod \ |
1017 | + ../include/vector_tools.mod |
1018 | |
1019 | ../include/k_epsilon.mod: k_epsilon.o |
1020 | @true |
1021 | |
1022 | === modified file 'parameterisation/Makefile.in' |
1023 | --- parameterisation/Makefile.in 2013-02-25 18:41:05 +0000 |
1024 | +++ parameterisation/Makefile.in 2013-10-25 15:24:41 +0000 |
1025 | @@ -47,7 +47,7 @@ |
1026 | OBJS = Equation_of_State.o \ |
1027 | Gls_vertical_turbulence_model.o \ |
1028 | k_epsilon.o \ |
1029 | -iceshelf_meltrate_surf_normal.o |
1030 | +Ice_Melt_Interface.o |
1031 | |
1032 | .SUFFIXES: .F90 .c .o .a |
1033 | |
1034 | |
1035 | === removed file 'parameterisation/iceshelf_meltrate_surf_normal.F90' |
1036 | --- parameterisation/iceshelf_meltrate_surf_normal.F90 2011-04-07 12:42:58 +0000 |
1037 | +++ parameterisation/iceshelf_meltrate_surf_normal.F90 1970-01-01 00:00:00 +0000 |
1038 | @@ -1,678 +0,0 @@ |
1039 | -! Copyright (C) 2006 Imperial College London and others. |
1040 | -! |
1041 | -! Please see the AUTHORS file in the main source directory for a full list |
1042 | -! of copyright holders. |
1043 | -! |
1044 | -! Prof. C Pain |
1045 | -! Applied Modelling and Computation Group |
1046 | -! Department of Earth Science and Engineering |
1047 | -! Imperial College London |
1048 | -! |
1049 | -! amcgsoftware@imperial.ac.uk |
1050 | -! |
1051 | -! This library is free software; you can redistribute it and/or |
1052 | -! modify it under the terms of the GNU Lesser General Public |
1053 | -! License as published by the Free Software Foundation, |
1054 | -! version 2.1 of the License. |
1055 | -! |
1056 | -! This library is distributed in the hope that it will be useful, |
1057 | -! but WITHOUT ANY WARRANTY; without even the implied arranty of |
1058 | -! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1059 | -! Lesser General Public License for more details. |
1060 | -! |
1061 | -! You should have received a copy of the GNU Lesser General Public |
1062 | -! License along with this library; if not, write to the Free Software |
1063 | -! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
1064 | -! USA |
1065 | - |
1066 | -#include "fdebug.h" |
1067 | - |
1068 | -module iceshelf_meltrate_surf_normal |
1069 | - use quadrature |
1070 | - use elements |
1071 | - use field_derivatives |
1072 | - use fields |
1073 | - use field_options |
1074 | - use fields_allocates |
1075 | - use state_module |
1076 | - use spud |
1077 | - use global_parameters, only: FIELD_NAME_LEN, OPTION_PATH_LEN |
1078 | - use state_fields_module |
1079 | - use boundary_conditions |
1080 | - use fields_manipulation |
1081 | - use surface_integrals |
1082 | - use fetools |
1083 | - use vector_tools |
1084 | - use FLDebug |
1085 | - use integer_set_module |
1086 | - use pickers_inquire |
1087 | - use transform_elements |
1088 | - use state_fields_module |
1089 | -implicit none |
1090 | - |
1091 | - private |
1092 | - real, save :: c0, cI, L, TI, & |
1093 | - a, b, gammaT, gammaS,Cd, dist_meltrate |
1094 | - integer, save :: nnodes,dimen |
1095 | - |
1096 | - type(vector_field), save :: surface_positions |
1097 | - type(vector_field), save :: funky_positions |
1098 | - type(integer_set), save :: sf_nodes !Nodes at the surface |
1099 | - !BC |
1100 | - integer, dimension(:), pointer, save :: ice_element_list |
1101 | - ! these are the fields and variables for the surface values |
1102 | - type(scalar_field), save :: ice_surfaceT,ice_surfaceS! these are used to populate the bcs |
1103 | - public :: melt_surf_init, melt_allocate_surface, melt_surf_calc, melt_bc |
1104 | - |
1105 | - |
1106 | - |
1107 | -contains |
1108 | - |
1109 | -!---------- |
1110 | -! initialise parameters based on options |
1111 | -!---------- |
1112 | - |
1113 | - subroutine melt_surf_init(state) |
1114 | - |
1115 | - type(state_type), intent(inout) :: state |
1116 | - character(len=OPTION_PATH_LEN) :: melt_path |
1117 | - ! hack |
1118 | - type(scalar_field), pointer :: T,S |
1119 | - ! When bc=Dirichlet |
1120 | - character(len=FIELD_NAME_LEN) :: bc_type |
1121 | - type(integer_set) :: surface_ids |
1122 | - integer, dimension(:),allocatable :: surf_id |
1123 | - integer, dimension(:), allocatable :: sf_nodes_ar |
1124 | - integer, dimension(2) :: shape_option |
1125 | - type(mesh_type), pointer :: mesh |
1126 | - type(mesh_type) :: surface_mesh |
1127 | - integer, dimension(:), pointer :: surface_nodes ! allocated and returned by create_surface_mesh |
1128 | - integer, dimension(:), allocatable :: surface_element_list |
1129 | - integer :: i,the_node |
1130 | - |
1131 | - melt_path = "/ocean_forcing/iceshelf_meltrate/Holland08" |
1132 | - |
1133 | - |
1134 | - ewrite(1,*) "--------Begin melt_init-------------" |
1135 | - |
1136 | - ! Get the 6 model constants |
1137 | - call get_option(trim(melt_path)//'/c0', c0, default = 3974.0) |
1138 | - call get_option(trim(melt_path)//'/cI', cI, default = 2009.0) |
1139 | - call get_option(trim(melt_path)//'/L', L, default = 3.35e5) |
1140 | - call get_option(trim(melt_path)//'/TI', TI, default = -25.0) |
1141 | - call get_option(trim(melt_path)//'/a', a, default = -0.0573) |
1142 | - call get_option(trim(melt_path)//'/b', b, default = 0.0832) |
1143 | - call get_option(trim(melt_path)//'/Cd', Cd, default = 1.5e-3) |
1144 | - call get_option(trim(melt_path)//'/melt_LayerLength', dist_meltrate) |
1145 | - |
1146 | - gammaT = sqrt(Cd)/(12.5*(7.0**(2.0/3.0))-9.0) |
1147 | - gammaS = sqrt(Cd)/(12.5*(700.0**(2.0/3.0))-9.0) |
1148 | - |
1149 | - !! bc= Dirichlet initialize T and S at the ice-ocean interface |
1150 | - !hack |
1151 | - !This change with bc type |
1152 | - call get_option("/ocean_forcing/iceshelf_meltrate/Holland08/calculate_boundaries", bc_type) |
1153 | - |
1154 | - select case(bc_type) |
1155 | - case("neumann") |
1156 | - |
1157 | - |
1158 | - case("dirichlet") |
1159 | - !! Define the values at ice-ocean interface |
1160 | - ! Get the surface_id of the ice-ocean interface |
1161 | - shape_option=option_shape(trim(melt_path)//"/melt_surfaceID") |
1162 | - allocate(surf_id(1:shape_option(1))) |
1163 | - call get_option(trim(melt_path)//'/melt_surfaceID',surf_id) |
1164 | - call allocate(surface_ids) |
1165 | - call insert(surface_ids,surf_id) |
1166 | - mesh => extract_mesh(state,"VelocityMesh") |
1167 | - ! Input, mesh, surface_id |
1168 | - ! Output surface_mesh,surface_element_list |
1169 | - call melt_surf_mesh(mesh,surface_ids,surface_mesh,surface_nodes,surface_element_list) |
1170 | - |
1171 | - T => extract_scalar_field(state,"Temperature") |
1172 | - S => extract_scalar_field(state,"Salinity") |
1173 | - do i=1,size(surface_nodes) |
1174 | - the_node = surface_nodes(i) |
1175 | - |
1176 | - call set(T,the_node,0.0) |
1177 | - call set(S,the_node,34.0) |
1178 | - |
1179 | - enddo |
1180 | -! T_bc => extract_scalar_field(state,"Tb") |
1181 | -! S_bc => extract_scalar_field(state,"Sb") |
1182 | - case default |
1183 | - FLAbort('Unknown BC for TKE') |
1184 | - end select |
1185 | - |
1186 | - |
1187 | - ewrite(1,*) "---------End melt_surf_init---------------------------------" |
1188 | - |
1189 | - end subroutine melt_surf_init |
1190 | - |
1191 | -subroutine melt_allocate_surface(state) |
1192 | - |
1193 | - type(state_type), intent(inout) :: state |
1194 | - type(vector_field), pointer :: positions |
1195 | - type(mesh_type), pointer :: mesh |
1196 | - type(mesh_type) :: surface_mesh |
1197 | - type(integer_set) :: surface_elements |
1198 | - integer, dimension(:), pointer :: surface_nodes ! allocated and returned by create_surface_mesh |
1199 | - integer, dimension(:), allocatable :: surface_element_list |
1200 | - integer :: ele, face,i,j,k |
1201 | -!! The local coordinates of the coordinate in the owning element |
1202 | -!! real, dimension(:), allocatable :: local_coord, local_coord_surf |
1203 | - real, dimension(:), allocatable :: coord |
1204 | -! for transform_facet_to_physical |
1205 | - real, dimension(:,:), allocatable :: normal |
1206 | - real, dimension(:), allocatable :: av_normal !Average of normal |
1207 | -!! integer, dimension(:), pointer :: ele_faces,face_neighs |
1208 | - type(element_type), pointer :: x_shape_f |
1209 | - real :: al,be,ga |
1210 | - real, dimension(:), allocatable :: xyz !New location of surface_mesh, dist_meltrate away from the boundary |
1211 | -!integer, save :: melt_surfaceID |
1212 | - character(len=OPTION_PATH_LEN) :: path |
1213 | - type(integer_set) :: surface_ids |
1214 | - integer, dimension(:),allocatable :: surf_id |
1215 | - |
1216 | -! For the vector averaging schem, taking the area of the surface element etc |
1217 | - real, dimension(:,:), allocatable :: table |
1218 | - integer, dimension(:,:), allocatable :: node_occupants |
1219 | - integer :: st,en,node,dim_vec |
1220 | - real :: area_sum |
1221 | - integer, dimension(:), allocatable :: sf_nodes_ar |
1222 | - integer, dimension(2) :: shape_option |
1223 | - |
1224 | - ewrite(1,*) "-------Begin melt_allocate_surface---------" |
1225 | - path = "/ocean_forcing/iceshelf_meltrate/Holland08" |
1226 | - ! Get the surface_id of the ice-ocean interface |
1227 | - shape_option=option_shape(trim(path)//"/melt_surfaceID") |
1228 | - allocate(surf_id(1:shape_option(1))) |
1229 | - call get_option(trim(path)//'/melt_surfaceID',surf_id) |
1230 | - call allocate(surface_ids) |
1231 | - call insert(surface_ids,surf_id) |
1232 | -! deallocate(surf_id) |
1233 | -! ewrite(1,*) "aft_surface_ids: ", set2vector(surface_ids) |
1234 | - |
1235 | - mesh => extract_mesh(state,"VelocityMesh") |
1236 | -! Input, mesh, surface_id |
1237 | -! Output surface_mesh,surface_element_list |
1238 | - call melt_surf_mesh(mesh,surface_ids,surface_mesh,surface_nodes,surface_element_list) |
1239 | - |
1240 | - positions => extract_vector_field(state,"Coordinate") |
1241 | -!SINK THE surface_mesh!! |
1242 | -! call get_option("/geometry/dimension/", dimension) |
1243 | - call allocate(surface_positions,positions%dim,mesh,"MySurfacePosition") |
1244 | - call allocate(funky_positions,surface_positions%dim, surface_positions%mesh,"MyFunkyPosition") |
1245 | - |
1246 | - |
1247 | -! Remap the positions vector to the surface mesh, surface_positions |
1248 | - call remap_field_to_surface(positions, surface_positions, surface_element_list) |
1249 | - |
1250 | -! Loop over # of surface elements |
1251 | -!nf = size(surface_element_list) |
1252 | -!2 comes because there are 2 nodes per a surface_element (assumption!) |
1253 | -! this number could be three for 3D problem, room for change |
1254 | -! dim_vec is the dimension of the positions, either 2 or 3. |
1255 | -! node_occupants(1,1:dim_vec*nf) = nodes that occupies the surface elements |
1256 | -! node_occupants(2,:) = surface elements |
1257 | -! table(1,:) = area of the face |
1258 | -! table(2,:) = normal_x |
1259 | -! table(3,:) = normal_y |
1260 | -! table(4,:) = normal_z |
1261 | - dim_vec = positions%dim |
1262 | - allocate(coord(dim_vec)) |
1263 | - allocate(node_occupants(2,dim_vec*size(surface_element_list))) |
1264 | - allocate(table(dim_vec+1,dim_vec*size(surface_element_list))) |
1265 | - allocate(av_normal(dim_vec)) |
1266 | - allocate(xyz(dim_vec)) |
1267 | - |
1268 | - do i=1,size(surface_element_list) |
1269 | - st = 1+dim_vec*(i-1) |
1270 | - en = dim_vec+dim_vec*(i-1) |
1271 | - face = surface_element_list(i) |
1272 | - node_occupants(2,st:en) = face |
1273 | - node_occupants(1,st:en) = face_global_nodes(positions, face) |
1274 | - ! Calculate the area of the surface element |
1275 | - ! For 2D, the area is the length |
1276 | - if (dim_vec .eq. 2) then |
1277 | - table(1,st:en) = calc_area2(positions,node_occupants(1,st:en)) |
1278 | - endif |
1279 | - |
1280 | - ! For 3D, the area become the area of the triangle (assumption here). |
1281 | - ! Subroutine calc_area3 uses Heron's formula. |
1282 | - if (dim_vec .eq. 3) then |
1283 | - table(1,st:en) = calc_area3(positions,node_occupants(1,st:en)) |
1284 | - endif |
1285 | - ! Compute the normal vector at the surface element. |
1286 | - x_shape_f=>face_shape(positions,face) |
1287 | - allocate(normal(dim_vec,x_shape_f%ngi)) !(dim x x_shape_f%ngi) |
1288 | - call transform_facet_to_physical(positions, face, normal=normal) |
1289 | - av_normal = sum(normal,2) |
1290 | - !"normal" should be the same; since the normal vector on the quadrature point does not change. |
1291 | - av_normal = av_normal/(sum(av_normal*av_normal))**(0.5) ! normalize the vector |
1292 | - deallocate(normal) |
1293 | - !Since av_normal is outward to the boundary, we will put -sign. We want the vector into the boundary |
1294 | - av_normal = -av_normal |
1295 | - ! Store av_normal, the normal vector averaged over quadrature points, in table |
1296 | - do j=1,dim_vec |
1297 | - table(j+1,st:en)=av_normal(j) |
1298 | - enddo |
1299 | - enddo |
1300 | -!! Now loop over surface_nodes |
1301 | -! ewrite(1,*) "table(1,1:3): ", table(1,1:3) |
1302 | -! ewrite(1,*) "table(2,1:3),normal_x: ", table(2,1:3) |
1303 | -! ewrite(1,*) "table(3,1:3),normal_y: ", table(3,1:3) |
1304 | -! ewrite(1,*) "table(4,1:3),normal_z: ", table(4,1:3) |
1305 | -!!In this loop, we will average adjacent normal vectors, using the area of the surface elements. |
1306 | - |
1307 | - !allocate(sf_nodes_ar(size(node_occupants(1,:)))) |
1308 | - call allocate(sf_nodes) |
1309 | -! call insert(sf_nodes,sf_nodes_ar) |
1310 | - do i=1,size(node_occupants(1,:)) |
1311 | - node = node_occupants(1,i) |
1312 | - av_normal(:) = 0.0 |
1313 | - area_sum = 0.0 |
1314 | - ! This loop average the normal vector based on the areas of surface elements |
1315 | - !, which share the "node". Using hash table may speed up this process |
1316 | - do j=1,size(node_occupants(1,:)) |
1317 | - !Pick the surface elements that sheare the "node" |
1318 | - if (node_occupants(1,j) .eq. node) then |
1319 | - do k=1,dim_vec |
1320 | - !table(1,j) = area of the surface element |
1321 | - av_normal(k) = av_normal(k) + table(k+1,j)*table(1,j) |
1322 | - enddo |
1323 | - !The total areas of the surface elements that occupies the "node" |
1324 | - area_sum = area_sum + table(1,j) |
1325 | - endif |
1326 | - enddo |
1327 | - |
1328 | - av_normal = av_normal / area_sum |
1329 | - ! normalize |
1330 | - av_normal = av_normal/(sum(av_normal*av_normal))**(0.5) |
1331 | - |
1332 | - dist_meltrate = abs(dist_meltrate) |
1333 | - ! Shift the location of the surface nodes. |
1334 | - !The coordinate of the surface node. |
1335 | - |
1336 | - coord = node_val(positions,node) |
1337 | - |
1338 | - ! dist_meltrate = ||xyz - coord|| xyz and coord are vectors |
1339 | - xyz = av_normal*dist_meltrate + coord |
1340 | - |
1341 | - call set(funky_positions,node,xyz) ! Set the coordinate of sinked nodes, funky positions. |
1342 | - |
1343 | - call set(surface_positions,node,coord) !Original coordinate of the surface |
1344 | -!! ewrite(1,*) "--------------------------------" |
1345 | -!! ewrite(1,*) "node: ", node |
1346 | -!! ewrite(1,*) "av_normal: ", av_normal |
1347 | -!! ewrite(1,*) "funky: ", xyz |
1348 | -!! ewrite(1,*) "coord: ", coord |
1349 | -!! ! Save the corresponding node number. |
1350 | -!! !sf_nodes_ar(i) = node |
1351 | - call insert(sf_nodes,node) |
1352 | - |
1353 | - node = 0 |
1354 | - enddo |
1355 | - |
1356 | - |
1357 | - deallocate(coord) |
1358 | - deallocate(table) |
1359 | - deallocate(node_occupants) |
1360 | - deallocate(av_normal) |
1361 | - deallocate(xyz) |
1362 | - call deallocate(surface_ids) |
1363 | - ewrite(1,*) "-------End melt_allocate_surface---------" |
1364 | -end subroutine melt_allocate_surface |
1365 | - |
1366 | - |
1367 | - |
1368 | -! Calculate the melt rate |
1369 | - subroutine melt_surf_calc(state) |
1370 | - |
1371 | - type(state_type), intent(inout) :: state |
1372 | - type(scalar_field), pointer :: Tb, Sb,MeltRate,Heat_flux,Salt_flux |
1373 | - type(scalar_field), pointer :: scalarfield |
1374 | - type(vector_field), pointer :: velocity,positions |
1375 | - !Debugging purpose pointer |
1376 | - type(scalar_field), pointer :: T_loc,S_loc,P_loc |
1377 | - type(vector_field), pointer :: V_loc,Location,Location_org |
1378 | - real, dimension(:), allocatable :: vel |
1379 | - integer :: i,j,k |
1380 | - ! Some internal variables |
1381 | - real :: speed, T,S,P,Aa,Bb,Cc,topo |
1382 | - real ::loc_Tb,loc_Sb,loc_meltrate,loc_heatflux,loc_saltflux |
1383 | - ! Aa*Sb^2+Bv*Sb+Cc |
1384 | - real :: arg = -1.0 |
1385 | - !Sink mesh part |
1386 | - integer :: ele,face,node,stat,the_node |
1387 | - real, dimension(:), allocatable :: local_coord,coord |
1388 | - type(element_type), pointer :: x_shape_f |
1389 | - integer, dimension(:), allocatable :: surface_node_list,node_lists |
1390 | - type(scalar_field) :: re_temperature,re_salinity,re_pressure |
1391 | - type(vector_field) :: re_velocity |
1392 | - |
1393 | - |
1394 | - ewrite(1,*) "-------Begin melt_surf_calc------------" |
1395 | - |
1396 | - MeltRate => extract_scalar_field(state,"MeltRate") |
1397 | - Tb => extract_scalar_field(state,"Tb") |
1398 | - Sb => extract_scalar_field(state,"Sb") |
1399 | - call set(MeltRate,setnan(arg)) |
1400 | - call set(Tb,setnan(arg)) |
1401 | - call set(Sb,setnan(arg)) |
1402 | - Heat_flux => extract_scalar_field(state,"Heat_flux") |
1403 | - Salt_flux => extract_scalar_field(state,"Salt_flux") |
1404 | - call set(Heat_flux,setnan(arg)) |
1405 | - call set(Salt_flux,setnan(arg)) |
1406 | - |
1407 | -! Debugging |
1408 | - T_loc => extract_scalar_field(state,"Tloc") |
1409 | - S_loc => extract_scalar_field(state,"Sloc") |
1410 | - P_loc => extract_scalar_field(state,"Ploc") |
1411 | - V_loc => extract_vector_field(state,"Vloc") |
1412 | - Location => extract_vector_field(state,"Location") |
1413 | - Location_org => extract_vector_field(state,"Location_org") |
1414 | - call set(T_loc,setnan(arg)) |
1415 | - call set(S_loc,setnan(arg)) |
1416 | - call set(P_loc,setnan(arg)) |
1417 | - allocate(vel(V_loc%dim)) |
1418 | - vel = setnan(arg) |
1419 | - call set(V_loc,vel) |
1420 | - call set(Location,vel) |
1421 | - call set(Location_org,vel) |
1422 | - |
1423 | - positions => extract_vector_field(state,"Coordinate") |
1424 | - !my positions |
1425 | - |
1426 | - ! Surface node list |
1427 | - allocate(surface_node_list(key_count(sf_nodes))) |
1428 | - ! Make it to vector from integer_set. |
1429 | - ! sf_nodes is calculated in "melt_allocate_surface" |
1430 | - surface_node_list=set2vector(sf_nodes) |
1431 | - |
1432 | - ! Remap temperature, salinity, pressure, and velocity onto positions mesh |
1433 | - scalarfield => extract_scalar_field(state,"Temperature") |
1434 | - |
1435 | - call allocate(re_temperature,positions%mesh,name="ReTemperature") |
1436 | - |
1437 | - call remap_field(scalarfield,re_temperature,stat) |
1438 | - |
1439 | - ! Salinity |
1440 | - scalarfield=> extract_scalar_field(state,"Salinity") |
1441 | - |
1442 | - call allocate(re_salinity,positions%mesh, name="ReSalinity") |
1443 | - call remap_field(scalarfield,re_salinity,stat) |
1444 | - |
1445 | - ! Pressure |
1446 | - scalarfield => extract_scalar_field(state,"Pressure") |
1447 | - call allocate(re_pressure,positions%mesh, name="RePressure") |
1448 | - call remap_field(scalarfield,re_pressure,stat) |
1449 | - |
1450 | - ! Velocity |
1451 | - velocity => extract_vector_field(state,"Velocity") |
1452 | - call allocate(re_velocity,velocity%dim,positions%mesh,name="ReVelocity") |
1453 | - call remap_field(velocity, re_velocity, stat) |
1454 | - |
1455 | - allocate(local_coord(positions%dim+1)) |
1456 | - allocate(coord(positions%dim)) |
1457 | - |
1458 | - |
1459 | - |
1460 | - |
1461 | -!!!!!!!!!!!!!!!!!!!!!!!!! |
1462 | - !surface_positions |
1463 | - |
1464 | - !! Loope over the surface nodes to calculate melt rate etc. |
1465 | - do i=1,size(surface_node_list) |
1466 | - the_node = surface_node_list(i) |
1467 | - !!! Interpolating |
1468 | - coord = node_val(funky_positions,the_node) |
1469 | - call picker_inquire(positions, coord, ele, local_coord,global=.true.) |
1470 | - |
1471 | - !! If sum(local_coord) is not equal to 1, |
1472 | - !! we know that this coord (funky position) does not exist in the domain. |
1473 | - |
1474 | - if (sum(local_coord) .gt. 2.0) then |
1475 | - ewrite(1,*) "Funk coord: ", node_val(funky_positions,the_node) |
1476 | - !! node_val(surface_positions,the_node) = node_val(positions,the_node) |
1477 | - ewrite(1,*) "Original ele: ",ele |
1478 | - ewrite(1,*) "sum of local_coord: ", sum(local_coord) |
1479 | - FLExit("Your funky_positions is out of the domain. Change melt_LayerLength.") |
1480 | - endif |
1481 | - !Number of nodes per element |
1482 | - allocate(node_lists(ele_and_faces_loc(positions, ele))) |
1483 | - node_lists = ele_nodes(positions,ele) !Lists of nodes that occupies the element. |
1484 | - ! This method of finding values at funky_positions works for P1, which are T,S, and velocity. |
1485 | - coord = 0.0 |
1486 | - T = 0.0 |
1487 | - S = 0.0 |
1488 | - speed = 0.0 |
1489 | - vel = 0.0 |
1490 | - |
1491 | - do j=1,size(node_lists) |
1492 | - node = node_lists(j) |
1493 | - coord = coord + node_val(positions,node)*local_coord(j) |
1494 | - T = T + node_val(re_temperature,node)*local_coord(j) |
1495 | - S = S + node_val(re_salinity,node)*local_coord(j) |
1496 | - vel = vel + node_val(re_velocity,node)*local_coord(j) |
1497 | - enddo |
1498 | - deallocate(node_lists) |
1499 | - ! Luckly P needs to be at the surface for the three equations |
1500 | - P = node_val(re_pressure,the_node) |
1501 | - speed = sqrt(sum(vel**2)) |
1502 | - |
1503 | - if (speed .lt. 0.001) then |
1504 | - speed = 0.001 |
1505 | - !ewrite(1,*) "----------iceshelf, speed less----", the_node,speed |
1506 | - endif |
1507 | - topo = -7.53e-8*P ! constant = -7.53e-8 [C Pa^(-1)] comes from Holland and Jenkins Table 1 |
1508 | - |
1509 | - !! Define Aa,Bb,Cc |
1510 | - !! Aa*Sb**2 + Bb*Sb + Cc = 0.0 |
1511 | - Aa = -gammaS*speed*cI*a + a*c0*gammaT*speed |
1512 | - |
1513 | - Bb = -gammaS*speed*L + gammaS*speed*S*cI*a |
1514 | - Bb = Bb - gammaS*speed*cI*(b+topo) + gammaS*speed*cI*TI |
1515 | - Bb = Bb - c0*gammaT*speed*T + c0*gammaT*speed*(b+topo) |
1516 | - |
1517 | - Cc = gammaS*speed*S*L +gammaS*speed*S*cI*(b+topo) + gammaS*speed*S*(-cI*TI) |
1518 | - |
1519 | - |
1520 | - !! This could be a linear equation if Aa=0 |
1521 | - if (Aa .eq. 0.0) then |
1522 | - loc_Sb = -Cc/Bb |
1523 | - else |
1524 | - !! Calculate for the 2nd oewrite(1,*) "size(surface_element_list)"rder polynomial. |
1525 | - !! We have two solutions. |
1526 | - loc_Sb = (-Bb + sqrt(Bb**2 - 4.0*Aa*Cc))/(2.0*Aa) |
1527 | - !! loc_Sb has to be larger than 0; since the salinity in the ocean is positive definite. |
1528 | - if (loc_Sb .lt. 0.0) then |
1529 | - loc_Sb = (-Bb - sqrt(Bb**2 - 4.0*Aa*Cc))/(2.0*Aa) |
1530 | - endif |
1531 | - endif |
1532 | - !ewrite(1,*) "----------iceshelf, loc_Sb----", loc_Sb |
1533 | - loc_Tb = a*loc_Sb + b + topo |
1534 | - loc_meltrate = gammaS*speed*(S-loc_Sb)/loc_Sb |
1535 | - !! Heat flux to the ocean |
1536 | - loc_heatflux = c0*(gammaT*speed+ loc_meltrate)*(T-loc_Tb) ! or loc_meltrate*L + loc_meltrate*cI*(loc_Tb-TI) |
1537 | - loc_saltflux = (gammaS*speed+loc_meltrate)*(S-loc_Sb) |
1538 | - !! Some debugging |
1539 | - !!ewrite(1,*) "melt_rate: ",loc_meltrate |
1540 | - !!ewrite(1,*) "tLHS: ", c0*gammaT*speed*(T-loc_Tb) |
1541 | - !!ewrite(1,*) "tRHS: ", loc_meltrate*L + loc_meltrate*cI*(loc_Tb-TI) |
1542 | - !!ewrite(1,*) "sLHS: ", gammaS*speed*(S-loc_Sb) |
1543 | - !!ewrite(1,*) "sRHS: ", loc_meltrate*loc_Sb |
1544 | - !!ewrite(1,*) "bLHS: ", loc_Tb |
1545 | - !!ewrite(1,*) "bRHS: ", a*loc_Sb + b + topo |
1546 | - |
1547 | - !! These are needed to implement BCs. |
1548 | - call set(MeltRate, the_node, loc_meltrate) |
1549 | - call set(Tb, the_node, loc_Tb) |
1550 | - call set(Sb, the_node, loc_Sb) |
1551 | - call set(Heat_flux, the_node,loc_heatflux) |
1552 | - call set(Salt_flux, the_node,loc_saltflux) |
1553 | - !! More or less for debugging purposes. |
1554 | - call set(T_loc,the_node,T) |
1555 | - call set(S_loc,the_node,S) |
1556 | - call set(P_loc,the_node,P) |
1557 | - call set(V_loc,the_node,vel) |
1558 | - call set(Location,the_node,node_val(funky_positions,the_node)) |
1559 | - call set(Location_org,the_node,node_val(positions,the_node)) |
1560 | - !! BC test |
1561 | - !!call set(TT,the_node,11.1) |
1562 | -! ewrite(1,*) "----------iceshelf, loc_saltflux----", the_node,loc_saltflux |
1563 | -! ewrite(1,*) "----------melt_surf_calc, loc_Tb----", the_node,loc_Tb |
1564 | -! ewrite(1,*) "----------iceshelf, surfaceS----",node_val(re_salinity,the_node) |
1565 | -! ewrite(1,*) "----------line 477 iceshelf, loc_meltrate----",loc_meltrate |
1566 | -! ewrite(1,*) "----------iceshelf, node_val(TT,the_node)----",node_val(TT,the_node) |
1567 | - enddo |
1568 | - |
1569 | - deallocate(local_coord) |
1570 | - deallocate(coord) |
1571 | - ewrite(1,*) "-----END melt_surf_calc-------" |
1572 | -end subroutine melt_surf_calc |
1573 | - |
1574 | - |
1575 | -subroutine melt_bc(state) |
1576 | - type(state_type), intent(inout) :: state |
1577 | - !! BC |
1578 | - type(scalar_field), pointer :: TT,SS |
1579 | - type(scalar_field), pointer :: scalar_surface |
1580 | - type(mesh_type), pointer :: ice_mesh |
1581 | - character(len=FIELD_NAME_LEN) :: bc_type |
1582 | - type(scalar_field), pointer :: T_bc,S_bc |
1583 | - integer, dimension(:), allocatable :: surface_node_list |
1584 | - integer :: i, the_node |
1585 | -!! Insert BC for temperature and salinity. This could be a separate subroutine |
1586 | - |
1587 | - |
1588 | - TT=> extract_scalar_field(state,"Temperature") |
1589 | - SS => extract_scalar_field(state,"Salinity") |
1590 | - |
1591 | - !This change with bc type |
1592 | - call get_option("/ocean_forcing/iceshelf_meltrate/Holland08/calculate_boundaries", bc_type) |
1593 | - |
1594 | - select case(bc_type) |
1595 | - case("neumann") |
1596 | - T_bc => extract_scalar_field(state,"Heat_flux") |
1597 | - S_bc => extract_scalar_field(state,"Salt_flux") |
1598 | - do i=1,node_count(T_bc) |
1599 | - call set(T_bc,node_val(T_bc,i)*10.0**3) |
1600 | - call set(S_bc,node_val(S_bc,i)*10.0**3) |
1601 | - enddo |
1602 | - |
1603 | - case("dirichlet") |
1604 | - T_bc => extract_scalar_field(state,"Tb") |
1605 | - S_bc => extract_scalar_field(state,"Sb") |
1606 | - case default |
1607 | - FLAbort('Unknown BC for TKE') |
1608 | - end select |
1609 | - |
1610 | - |
1611 | - ! Surface node list |
1612 | - allocate(surface_node_list(key_count(sf_nodes))) |
1613 | - ! Make it to vector from integer_set. |
1614 | - ! sf_nodes is calculated in "melt_allocate_surface" |
1615 | - surface_node_list=set2vector(sf_nodes) |
1616 | - |
1617 | - ! create a surface mesh to place values onto. This is for the top surface |
1618 | - call get_boundary_condition(TT, 'temperature_iceshelf_BC', surface_mesh=ice_mesh) |
1619 | - call allocate(ice_surfaceT, ice_mesh, name="ice_surfaceT") |
1620 | - call get_boundary_condition(SS, 'salinity_iceshelf_BC', surface_mesh=ice_mesh) |
1621 | - call allocate(ice_surfaceS, ice_mesh, name="ice_surfaceS") |
1622 | - ! Define ice_surfaceT according to Heat_flux? |
1623 | - ewrite(1,*) "node_count(ice_surfaceT)",node_count(ice_surfaceT) |
1624 | - do i=1,node_count(ice_surfaceT) |
1625 | - the_node = surface_node_list(i) |
1626 | - call set(ice_surfaceT,i,node_val(T_bc,the_node)) |
1627 | - call set(ice_surfaceS,i,node_val(S_bc,the_node)) |
1628 | - enddo |
1629 | - !! Temperature |
1630 | - scalar_surface => extract_surface_field(TT, 'temperature_iceshelf_BC', "value") |
1631 | - call remap_field(ice_surfaceT, scalar_surface) |
1632 | - !! Salinity |
1633 | - scalar_surface => extract_surface_field(SS, 'salinity_iceshelf_BC', "value") |
1634 | - call remap_field(ice_surfaceS, scalar_surface) |
1635 | -! ewrite(1,*) "iceBC, ice_element_list",ice_element_list |
1636 | -! ewrite(1,*) "iceBC, node_count(scalar_surface)", node_count(scalar_surface) |
1637 | -! ewrite(1,*) "node_val(scalar_surface,1): ", node_val(scalar_surface,1) |
1638 | - |
1639 | -!! Insert BC for salinity |
1640 | - |
1641 | - |
1642 | -end subroutine melt_bc |
1643 | - |
1644 | - |
1645 | - |
1646 | -!!------------------------------------------------------------------! |
1647 | -!! Private subroutines ! |
1648 | -!!------------------------------------------------------------------! |
1649 | - |
1650 | -subroutine melt_surf_mesh(mesh,surface_ids,surface_mesh,surface_nodes,surface_element_list) |
1651 | - |
1652 | - type(mesh_type), intent(in) :: mesh |
1653 | - type(integer_set), intent(in) :: surface_ids |
1654 | - type(mesh_type), intent(out) :: surface_mesh |
1655 | - integer, dimension(:), pointer, intent(out) :: surface_nodes ! allocated and returned by create_surface_mesh |
1656 | - integer, dimension(:), allocatable, intent(out) :: surface_element_list |
1657 | - ! integer, dimension(:), allocatable :: surface_nodes_out |
1658 | - type(scalar_field) :: surface_field |
1659 | - type(integer_set) :: surface_elements |
1660 | - integer :: i |
1661 | - ! create a set of surface elements that have surface id in 'surface_ids' |
1662 | - |
1663 | - call allocate(surface_elements) |
1664 | - do i=1, surface_element_count(mesh) |
1665 | -! ewrite(1,*) "surf_normal surface_element_id(mesh, i)", surface_element_id(mesh, i) |
1666 | -! ewrite(1,*) "surf_normal surface_ids", set2vector(surface_ids) |
1667 | - if (has_value(surface_ids, surface_element_id(mesh, i))) then |
1668 | - call insert(surface_elements, i) |
1669 | - |
1670 | - end if |
1671 | - end do |
1672 | - |
1673 | - allocate(surface_element_list(key_count(surface_elements))) |
1674 | - surface_element_list=set2vector(surface_elements) |
1675 | - call create_surface_mesh(surface_mesh, surface_nodes, mesh, surface_element_list, name=trim(mesh%name)//"ToshisMesh") |
1676 | - |
1677 | - |
1678 | -end subroutine melt_surf_mesh |
1679 | - |
1680 | - |
1681 | -real function setnan(arg) |
1682 | - real :: arg |
1683 | - setnan = sqrt(arg) |
1684 | -end function |
1685 | - |
1686 | -real function calc_area2(positions,nodes) |
1687 | - type(vector_field), pointer :: positions |
1688 | - integer, dimension(2) :: nodes |
1689 | - real, dimension(2) :: coord1,coord2 |
1690 | -! real :: area |
1691 | - coord1 = node_val(positions,nodes(1)) |
1692 | - coord2 = node_val(positions,nodes(2)) |
1693 | - |
1694 | - calc_area2 = (sum((coord2 - coord1)**2))**0.5 |
1695 | - |
1696 | -end function |
1697 | - |
1698 | -real function calc_area3(positions,nodes) |
1699 | - type(vector_field), pointer :: positions |
1700 | - integer, dimension(3) :: nodes |
1701 | - real, dimension(3) :: coord1,coord2,coord3 |
1702 | - real :: a,b,c,s |
1703 | -! real :: area |
1704 | - coord1 = node_val(positions,nodes(1)) |
1705 | - coord2 = node_val(positions,nodes(2)) |
1706 | - coord3 = node_val(positions,nodes(3)) |
1707 | -! Use Heron's formula to calculate the area of triangle |
1708 | - a = (sum((coord2 - coord1)**2))**0.5 |
1709 | - b = (sum((coord3 - coord1)**2))**0.5 |
1710 | - c = (sum((coord2 - coord3)**2))**0.5 |
1711 | - s = 0.5*(a+b+c) |
1712 | - calc_area3 = (s*(s-a)*(s-b)*(s-c))**0.5 |
1713 | - |
1714 | -end function |
1715 | - |
1716 | -end module iceshelf_meltrate_surf_normal |
1717 | |
1718 | === modified file 'schemas/fluidity_options.rnc' |
1719 | --- schemas/fluidity_options.rnc 2013-10-11 10:48:07 +0000 |
1720 | +++ schemas/fluidity_options.rnc 2013-10-25 15:24:41 +0000 |
1721 | @@ -6528,6 +6528,33 @@ |
1722 | } |
1723 | ) |
1724 | }?, |
1725 | + ## Provide the hydrostatic pressure under the shelf |
1726 | + ## for the interface melt parameterisation |
1727 | + element scalar_field { |
1728 | + attribute rank { "0" }, |
1729 | + attribute name { "subshelf_hydrostatic_pressure" }, |
1730 | + ( |
1731 | + element diagnostic { |
1732 | + internal_algorithm, |
1733 | + velocity_mesh_choice, |
1734 | + diagnostic_scalar_field |
1735 | + } |
1736 | + ) |
1737 | + }?, |
1738 | + element subshelf_hydrostatic_pressure { |
1739 | + ( |
1740 | + ## Python function prescribing real input. Functions should be of the form: |
1741 | + ## |
1742 | + ## def val(t): |
1743 | + ## # Function code |
1744 | + ## return # Return value |
1745 | + ## |
1746 | + ## |
1747 | + element python { |
1748 | + python_code |
1749 | + } |
1750 | + ) |
1751 | + }?, |
1752 | ## Boundary stuff |
1753 | element calculate_boundaries { |
1754 | element string_value { |
1755 | |
1756 | === modified file 'schemas/fluidity_options.rng' |
1757 | --- schemas/fluidity_options.rng 2013-10-11 10:48:07 +0000 |
1758 | +++ schemas/fluidity_options.rng 2013-10-25 15:24:41 +0000 |
1759 | @@ -8228,6 +8228,37 @@ |
1760 | </element> |
1761 | </optional> |
1762 | <optional> |
1763 | + <element name="scalar_field"> |
1764 | + <a:documentation>Provide the hydrostatic pressure under the shelf |
1765 | +for the interface melt parameterisation</a:documentation> |
1766 | + <attribute name="rank"> |
1767 | + <value>0</value> |
1768 | + </attribute> |
1769 | + <attribute name="name"> |
1770 | + <value>subshelf_hydrostatic_pressure</value> |
1771 | + </attribute> |
1772 | + <element name="diagnostic"> |
1773 | + <ref name="internal_algorithm"/> |
1774 | + <ref name="velocity_mesh_choice"/> |
1775 | + <ref name="diagnostic_scalar_field"/> |
1776 | + </element> |
1777 | + </element> |
1778 | + </optional> |
1779 | + <optional> |
1780 | + <element name="subshelf_hydrostatic_pressure"> |
1781 | + <element name="python"> |
1782 | + <a:documentation>Python function prescribing real input. Functions should be of the form: |
1783 | + |
1784 | + def val(t): |
1785 | + # Function code |
1786 | + return # Return value |
1787 | + |
1788 | +</a:documentation> |
1789 | + <ref name="python_code"/> |
1790 | + </element> |
1791 | + </element> |
1792 | + </optional> |
1793 | + <optional> |
1794 | <element name="calculate_boundaries"> |
1795 | <a:documentation>Boundary stuff </a:documentation> |
1796 | <element name="string_value"> |