MODFLOW 6 version 6.9.0.dev0
USGS Modular Hydrologic Model
Loading...
Searching...
No Matches
swf-dfw.f90
Go to the documentation of this file.
1!> @brief Stream Network Flow (SWF) Diffusive Wave (DFW) Module
2!!
3!! This module solves one-dimensional flow routing using a diffusive
4!< wave approach.
5module swfdfwmodule
6
7 use kindmodule, only: dp, i4b, lgp
9 dzero, dhalf, done, dtwo, &
15 use simvariablesmodule, only: errmsg
19 use basedismodule, only: disbasetype
20 use swfcxsmodule, only: swfcxstype
21 use obsmodule, only: obstype, obs_cr
22 use observemodule, only: observetype
24
25 implicit none
26 private
27 public :: swfdfwtype, dfw_cr
28
29 !> @brief flags indicating which DFW options were found in the input
31 logical(LGP) :: icentral = .false.
32 logical(LGP) :: iswrcond = .false.
33 logical(LGP) :: lengthconv = .false.
34 logical(LGP) :: timeconv = .false.
35 logical(LGP) :: iprflow = .false.
36 logical(LGP) :: ipakcb = .false.
37 logical(LGP) :: isavvelocity = .false.
38 logical(LGP) :: obs6_filename = .false.
39 end type dfwoptionsfoundtype
40
41 !> @brief flags indicating which DFW griddata were found in the input
43 logical(LGP) :: manningsn = .false.
44 logical(LGP) :: idcxs = .false.
46
48
49 ! user-provided input
50 integer(I4B), pointer :: is2d => null() !< flag to indicate this model is 2D overland flow and not 1d channel flow
51 integer(I4B), pointer :: icentral => null() !< flag to use central in space weighting (default is upstream weighting)
52 integer(I4B), pointer :: iswrcond => null() !< flag to activate the dev SWR conductance formulation
53 real(dp), pointer :: unitconv !< conversion factor used in mannings equation; calculated from timeconv and lengthconv
54 real(dp), pointer :: timeconv !< conversion factor from model length units to meters (1.0 if model uses meters for length)
55 real(dp), pointer :: lengthconv !< conversion factor from model time units to seconds (1.0 if model uses seconds for time)
56 real(dp), dimension(:), pointer, contiguous :: hnew => null() !< pointer to model xnew
57 real(dp), dimension(:), pointer, contiguous :: manningsn => null() !< mannings roughness for each reach
58 integer(I4B), dimension(:), pointer, contiguous :: idcxs => null() !< cross section id for each reach
59 integer(I4B), dimension(:), pointer, contiguous :: ibound => null() !< pointer to model ibound
60 integer(I4B), dimension(:), pointer, contiguous :: icelltype => null() !< set to 1 and is accessed by chd for checking
61
62 ! velocity
63 integer(I4B), pointer :: icalcvelocity => null() !< flag to indicate velocity will be calculated (always on)
64 integer(I4B), pointer :: isavvelocity => null() !< flag to indicate velocity will be saved
65 real(dp), dimension(:, :), pointer, contiguous :: vcomp => null() !< velocity components: vx, vy, vz (nodes, 3)
66 real(dp), dimension(:), pointer, contiguous :: vmag => null() !< velocity magnitude (of size nodes)
67 integer(I4B), pointer :: nedges => null() !< number of cell edges
68 integer(I4B), pointer :: lastedge => null() !< last edge number
69 integer(I4B), dimension(:), pointer, contiguous :: nodedge => null() !< array of node numbers that have edges
70 integer(I4B), dimension(:), pointer, contiguous :: ihcedge => null() !< edge type (horizontal or vertical)
71 real(dp), dimension(:, :), pointer, contiguous :: propsedge => null() !< edge properties (Q, area, nx, ny, distance)
72 real(dp), dimension(:), pointer, contiguous :: grad_dhds_mag => null() !< magnitude of the gradient (of size nodes)
73 real(dp), dimension(:), pointer, contiguous :: dhdsja => null() !< gradient for each connection (of size njas)
74
75 ! observation data
76 integer(I4B), pointer :: inobspkg => null() !< unit number for obs package
77 type(obstype), pointer :: obs => null() !< observation package
78
79 ! pointer to cross section data
80 type(swfcxstype), pointer :: cxs
81
82 contains
83
84 procedure :: dfw_df
85 procedure :: allocate_scalars
86 procedure :: allocate_arrays
87 procedure :: dfw_load
88 procedure :: source_options
89 procedure :: log_options
90 procedure :: source_griddata
91 procedure :: log_griddata
92 procedure :: dfw_ar
93 procedure :: dfw_rp
94 procedure :: dfw_ad
95 procedure :: dfw_fc
96 procedure :: dfw_qnm_fc_nr
97 !procedure :: dfw_qnm_fc
98 procedure :: dfw_fn
99 procedure :: dfw_nur
100 procedure :: dfw_cq
101 procedure :: dfw_bd
104 procedure :: dfw_da
105 procedure :: dfw_df_obs
106 procedure :: dfw_rp_obs
107 procedure :: dfw_bd_obs
108 procedure :: qcalc
109 procedure :: get_cond
110 procedure :: get_cond_swr
111 procedure :: get_cond_n
112 procedure :: get_flow_area_nm
113 procedure :: calc_velocity
114 procedure :: sav_velocity
115 procedure, public :: increase_edge_count
116 procedure, public :: set_edge_properties
117 procedure :: calc_dhds
118 procedure :: write_cxs_tables
119
120 end type swfdfwtype
121
122contains
123
124 !> @brief create package
125 !<
126 subroutine dfw_cr(dfwobj, name_model, input_mempath, inunit, iout, &
127 cxs)
128 ! modules
130 ! dummy
131 type(swfdfwtype), pointer :: dfwobj !< object to create
132 character(len=*), intent(in) :: name_model !< name of the SWF model
133 character(len=*), intent(in) :: input_mempath !< memory path
134 integer(I4B), intent(in) :: inunit !< flag to indicate if package is active
135 integer(I4B), intent(in) :: iout !< unit number for output
136 type(swfcxstype), pointer, intent(in) :: cxs !< the pointer to the cxs package
137 ! locals
138 logical(LGP) :: found_fname
139 ! formats
140 character(len=*), parameter :: fmtheader = &
141 "(1x, /1x, 'DFW -- DIFFUSIVE WAVE (DFW) PACKAGE, VERSION 1, 9/25/2023', &
142 &' INPUT READ FROM MEMPATH: ', A, /)"
143 !
144 ! Create the object
145 allocate (dfwobj)
146
147 ! create name and memory path
148 call dfwobj%set_names(1, name_model, 'DFW', 'DFW')
149
150 ! Allocate scalars
151 call dfwobj%allocate_scalars()
152
153 ! Set variables
154 dfwobj%input_mempath = input_mempath
155 dfwobj%inunit = inunit
156 dfwobj%iout = iout
157
158 ! set name of input file
159 call mem_set_value(dfwobj%input_fname, 'INPUT_FNAME', dfwobj%input_mempath, &
160 found_fname)
161
162 ! Set a pointers to passed in objects
163 dfwobj%cxs => cxs
164
165 ! create obs package
166 call obs_cr(dfwobj%obs, dfwobj%inobspkg)
167
168 ! check if dfw is enabled
169 if (inunit > 0) then
170
171 ! Print a message identifying the package.
172 write (iout, fmtheader) input_mempath
173
174 end if
175
176 end subroutine dfw_cr
177
178 !> @brief load data from IDM to package
179 !<
180 subroutine dfw_df(this, dis)
181 ! dummy
182 class(swfdfwtype) :: this !< this instance
183 class(disbasetype), pointer, intent(inout) :: dis !< the pointer to the discretization
184
185 ! Set a pointers to passed in objects
186 this%dis => dis
187
188 ! Set the distype (either DISV1D or DIS2D)
189 if (this%dis%is_2d()) then
190 this%is2d = 1
191 end if
192
193 ! check if dfw is enabled
194 ! this will need to become if (.not. present(dfw_options)) then
195 !if (inunit > 0) then
196
197 ! allocate arrays
198 call this%allocate_arrays()
199
200 ! load dfw
201 call this%dfw_load()
202
203 !end if
204
205 end subroutine dfw_df
206
207 !> @ brief Allocate scalars
208 !!
209 !! Allocate and initialize scalars for the package. The base model
210 !! allocate scalars method is also called.
211 !!
212 !<
213 subroutine allocate_scalars(this)
214 ! modules
215 ! dummy
216 class(swfdfwtype) :: this !< this instance
217 !
218 ! allocate scalars in NumericalPackageType
219 call this%NumericalPackageType%allocate_scalars()
220 !
221 ! Allocate scalars
222 call mem_allocate(this%is2d, 'IS2D', this%memoryPath)
223 call mem_allocate(this%icentral, 'ICENTRAL', this%memoryPath)
224 call mem_allocate(this%iswrcond, 'ISWRCOND', this%memoryPath)
225 call mem_allocate(this%unitconv, 'UNITCONV', this%memoryPath)
226 call mem_allocate(this%lengthconv, 'LENGTHCONV', this%memoryPath)
227 call mem_allocate(this%timeconv, 'TIMECONV', this%memoryPath)
228 call mem_allocate(this%inobspkg, 'INOBSPKG', this%memoryPath)
229 call mem_allocate(this%icalcvelocity, 'ICALCVELOCITY', this%memoryPath)
230 call mem_allocate(this%isavvelocity, 'ISAVVELOCITY', this%memoryPath)
231 call mem_allocate(this%nedges, 'NEDGES', this%memoryPath)
232 call mem_allocate(this%lastedge, 'LASTEDGE', this%memoryPath)
233
234 this%is2d = 0
235 this%icentral = 0
236 this%iswrcond = 0
237 this%unitconv = done
238 this%lengthconv = done
239 this%timeconv = done
240 this%inobspkg = 0
241 this%icalcvelocity = 0
242 this%isavvelocity = 0
243 this%nedges = 0
244 this%lastedge = 0
245
246 end subroutine allocate_scalars
247
248 !> @brief allocate memory for arrays
249 !<
250 subroutine allocate_arrays(this)
251 ! dummy
252 class(swfdfwtype) :: this !< this instance
253 ! locals
254 integer(I4B) :: n
255 !
256 ! user-provided input
257 call mem_allocate(this%manningsn, this%dis%nodes, &
258 'MANNINGSN', this%memoryPath)
259 call mem_allocate(this%idcxs, this%dis%nodes, &
260 'IDCXS', this%memoryPath)
261 call mem_allocate(this%icelltype, this%dis%nodes, &
262 'ICELLTYPE', this%memoryPath)
263
264 ! optional arrays
265 call mem_allocate(this%nodedge, 0, 'NODEDGE', this%memoryPath)
266 call mem_allocate(this%ihcedge, 0, 'IHCEDGE', this%memoryPath)
267 call mem_allocate(this%propsedge, 0, 0, 'PROPSEDGE', this%memoryPath)
268
269 ! Specific discharge is (re-)allocated when nedges is known
270 call mem_allocate(this%vcomp, 3, 0, 'VCOMP', this%memoryPath)
271 call mem_allocate(this%vmag, 0, 'VMAG', this%memoryPath)
272
273 do n = 1, this%dis%nodes
274 this%manningsn(n) = dzero
275 this%idcxs(n) = 0
276 this%icelltype(n) = 1
277 end do
278
279 ! for 2d models, need to calculate and store dhds magnitude
280 if (this%is2d == 1) then
281 call mem_allocate(this%grad_dhds_mag, this%dis%nodes, &
282 'GRAD_DHDS_MAG', this%memoryPath)
283 call mem_allocate(this%dhdsja, this%dis%njas, &
284 'DHDSJA', this%memoryPath)
285 do n = 1, this%dis%nodes
286 this%grad_dhds_mag(n) = dzero
287 end do
288 do n = 1, this%dis%njas
289 this%dhdsja(n) = dzero
290 end do
291 end if
292
293 end subroutine allocate_arrays
294
295 !> @brief load data from IDM to package
296 !<
297 subroutine dfw_load(this)
298 ! dummy
299 class(swfdfwtype) :: this !< this instance
300
301 ! source input data
302 call this%source_options()
303 call this%source_griddata()
304
305 end subroutine dfw_load
306
307 !> @brief Copy options from IDM into package
308 !<
309 subroutine source_options(this)
310 ! modules
311 use kindmodule, only: lgp
315 ! dummy
316 class(swfdfwtype) :: this !< this instance
317 ! locals
318 integer(I4B) :: isize
319 type(dfwoptionsfoundtype) :: found
320 type(characterstringtype), dimension(:), pointer, &
321 contiguous :: obs6_fnames
322
323 ! update defaults with idm sourced values
324 call mem_set_value(this%icentral, 'ICENTRAL', &
325 this%input_mempath, found%icentral)
326 call mem_set_value(this%iswrcond, 'ISWRCOND', &
327 this%input_mempath, found%iswrcond)
328 call mem_set_value(this%lengthconv, 'LENGTHCONV', &
329 this%input_mempath, found%lengthconv)
330 call mem_set_value(this%timeconv, 'TIMECONV', &
331 this%input_mempath, found%timeconv)
332 call mem_set_value(this%iprflow, 'IPRFLOW', &
333 this%input_mempath, found%iprflow)
334 call mem_set_value(this%ipakcb, 'IPAKCB', &
335 this%input_mempath, found%ipakcb)
336 call mem_set_value(this%isavvelocity, 'ISAVVELOCITY', &
337 this%input_mempath, found%isavvelocity)
338
339 ! save flows option active
340 if (found%icentral) this%icentral = 1
341 if (found%ipakcb) this%ipakcb = -1
342
343 ! calculate unit conversion
344 this%unitconv = this%lengthconv**donethird
345 this%unitconv = this%unitconv * this%timeconv
346
347 ! save velocity active
348 if (found%isavvelocity) this%icalcvelocity = this%isavvelocity
349
350 ! check for obs6_filename
351 call get_isize('OBS6_FILENAME', this%input_mempath, isize)
352 if (isize > 0) then
353 !
354 if (isize /= 1) then
355 errmsg = 'Multiple OBS6 keywords detected in OPTIONS block.'// &
356 ' Only one OBS6 entry allowed.'
357 call store_error(errmsg)
358 call store_error_filename(this%input_fname)
359 end if
360
361 call mem_setptr(obs6_fnames, 'OBS6_FILENAME', this%input_mempath)
362
363 found%obs6_filename = .true.
364 this%obs%inputFilename = obs6_fnames(1)
365 this%obs%active = .true.
366 this%inobspkg = getunit()
367 this%obs%inUnitObs = this%inobspkg
368 call openfile(this%inobspkg, this%iout, this%obs%inputFilename, 'OBS')
369 call this%obs%obs_df(this%iout, this%packName, this%filtyp, this%dis)
370 call this%dfw_df_obs()
371
372 call memorystore_release('OBS6_FILENAME', this%input_mempath)
373 end if
374
375 ! log values to list file
376 if (this%iout > 0) then
377 call this%log_options(found)
378 end if
379
380 end subroutine source_options
381
382 !> @brief Write user options to list file
383 !<
384 subroutine log_options(this, found)
385 class(swfdfwtype) :: this !< this instance
386 type(dfwoptionsfoundtype), intent(in) :: found
387
388 write (this%iout, '(1x,a)') 'Setting DFW Options'
389
390 if (found%lengthconv) then
391 write (this%iout, '(4x,a, G0)') 'Mannings length conversion value &
392 &specified as ', this%lengthconv
393 end if
394
395 if (found%timeconv) then
396 write (this%iout, '(4x,a, G0)') 'Mannings time conversion value &
397 &specified as ', this%timeconv
398 end if
399
400 if (found%lengthconv .or. found%timeconv) then
401 write (this%iout, '(4x,a, G0)') 'Mannings conversion value calculated &
402 &from user-provided length_conversion and &
403 &time_conversion is ', this%unitconv
404 end if
405
406 if (found%iprflow) then
407 write (this%iout, '(4x,a)') 'Cell-by-cell flow information will be printed &
408 &to listing file whenever ICBCFL is not zero.'
409 end if
410
411 if (found%ipakcb) then
412 write (this%iout, '(4x,a)') 'Cell-by-cell flow information will be printed &
413 &to listing file whenever ICBCFL is not zero.'
414 end if
415
416 if (found%obs6_filename) then
417 write (this%iout, '(4x,a)') 'Observation package is active.'
418 end if
419
420 if (found%isavvelocity) &
421 write (this%iout, '(4x,a)') 'Velocity will be calculated at cell &
422 &centers and written to DATA-VCOMP in budget &
423 &file when requested.'
424
425 if (found%iswrcond) then
426 write (this%iout, '(4x,a, G0)') 'Conductance will be calculated using &
427 &the SWR development option.'
428 end if
429
430 write (this%iout, '(1x,a,/)') 'End Setting DFW Options'
431
432 end subroutine log_options
433
434 !> @brief copy griddata from IDM to package
435 !<
436 subroutine source_griddata(this)
437 ! modules
442 ! dummy
443 class(swfdfwtype) :: this !< this instance
444 ! locals
445 character(len=LENMEMPATH) :: idmMemoryPath
446 type(dfwgriddatafoundtype) :: found
447 integer(I4B), dimension(:), pointer, contiguous :: map
448
449 ! set memory path
450 idmmemorypath = create_mem_path(this%name_model, 'DFW', idm_context)
451
452 ! set map to convert user input data into reduced data
453 map => null()
454 if (this%dis%nodes < this%dis%nodesuser) map => this%dis%nodeuser
455
456 ! update defaults with idm sourced values
457 call mem_set_value(this%manningsn, 'MANNINGSN', &
458 idmmemorypath, map, found%manningsn)
459 call mem_set_value(this%idcxs, 'IDCXS', idmmemorypath, map, found%idcxs)
460
461 ! ensure MANNINGSN was found
462 if (.not. found%manningsn) then
463 write (errmsg, '(a)') 'Error in GRIDDATA block: MANNINGSN not found.'
464 call store_error(errmsg)
465 end if
466
467 if (count_errors() > 0) then
468 call store_error_filename(this%input_fname)
469 end if
470
471 ! log griddata
472 if (this%iout > 0) then
473 call this%log_griddata(found)
474 end if
475
476 end subroutine source_griddata
477
478 !> @brief log griddata to list file
479 !<
480 subroutine log_griddata(this, found)
481 class(swfdfwtype) :: this !< this instance
482 type(dfwgriddatafoundtype), intent(in) :: found
483
484 write (this%iout, '(1x,a)') 'Setting DFW Griddata'
485
486 if (found%manningsn) then
487 write (this%iout, '(4x,a)') 'MANNINGSN set from input file'
488 end if
489
490 if (found%idcxs) then
491 write (this%iout, '(4x,a)') 'IDCXS set from input file'
492 end if
493
494 call this%write_cxs_tables()
495
496 write (this%iout, '(1x,a,/)') 'End Setting DFW Griddata'
497
498 end subroutine log_griddata
499
500 subroutine write_cxs_tables(this)
501 ! modules
502 ! dummy
503 class(swfdfwtype) :: this !< this instance
504 ! local
505 ! integer(I4B) :: idcxs
506 ! integer(I4B) :: n
507
508 !-- TODO: write cross section tables
509 ! do n = 1, this%dis%nodes
510 ! idcxs = this%idcxs(n)
511 ! if (idcxs > 0) then
512 ! call this%cxs%write_cxs_table(idcxs, this%width(n), this%slope(n), &
513 ! this%manningsn(n), this%unitconv)
514 ! end if
515 ! end do
516 end subroutine write_cxs_tables
517
518 !> @brief allocate memory
519 !<
520 subroutine dfw_ar(this, ibound, hnew)
521 ! modules
522 ! dummy
523 class(swfdfwtype) :: this !< this instance
524 integer(I4B), dimension(:), pointer, contiguous :: ibound !< model ibound array
525 real(DP), dimension(:), pointer, contiguous, intent(inout) :: hnew !< pointer to model head array
526 ! local
527 integer(I4B) :: n
528
529 ! store pointer to ibound
530 this%ibound => ibound
531 this%hnew => hnew
532
533 if (this%icalcvelocity == 1) then
534 call mem_reallocate(this%vcomp, 3, this%dis%nodes, 'VCOMP', this%memoryPath)
535 call mem_reallocate(this%vmag, this%dis%nodes, 'VMAG', this%memoryPath)
536 call mem_reallocate(this%nodedge, this%nedges, 'NODEDGE', this%memoryPath)
537 call mem_reallocate(this%ihcedge, this%nedges, 'IHCEDGE', this%memoryPath)
538 call mem_reallocate(this%propsedge, 5, this%nedges, 'PROPSEDGE', &
539 this%memoryPath)
540 do n = 1, this%dis%nodes
541 this%vcomp(:, n) = dzero
542 this%vmag(n) = dzero
543 end do
544 end if
545
546 ! observation data
547 call this%obs%obs_ar()
548
549 end subroutine dfw_ar
550
551 !> @brief allocate memory
552 !<
553 subroutine dfw_rp(this)
554 ! modules
555 ! dummy
556 class(swfdfwtype) :: this !< this instance
557
558 ! read observations
559 call this%dfw_rp_obs()
560
561 end subroutine dfw_rp
562
563 !> @brief advance
564 !<
565 subroutine dfw_ad(this, irestore)
566 class(swfdfwtype) :: this !< this instance
567 integer(I4B), intent(in) :: irestore !< ATS flag for retrying time step (1) or advancing (0)
568
569 ! Push simulated values to preceding time/subtime step
570 call this%obs%obs_ad()
571
572 end subroutine dfw_ad
573
574 !> @brief fill coefficients
575 !!
576 !! The DFW Package is entirely Newton based. All matrix and rhs terms
577 !! are added from thish routine.
578 !!
579 !<
580 subroutine dfw_fc(this, kiter, matrix_sln, idxglo, rhs, stage, stage_old)
581 ! modules
582 ! dummy
583 class(swfdfwtype) :: this !< this instance
584 integer(I4B) :: kiter
585 class(matrixbasetype), pointer :: matrix_sln
586 integer(I4B), intent(in), dimension(:) :: idxglo
587 real(DP), intent(inout), dimension(:) :: rhs
588 real(DP), intent(inout), dimension(:) :: stage
589 real(DP), intent(inout), dimension(:) :: stage_old
590 ! local
591
592 ! calculate dhds at cell center for 2d case
593 if (this%is2d == 1) then
594 call this%calc_dhds()
595 end if
596
597 ! add qnm contributions to matrix equations
598 call this%dfw_qnm_fc_nr(kiter, matrix_sln, idxglo, rhs, stage, stage_old)
599
600 end subroutine dfw_fc
601
602 !> @brief fill coefficients
603 !!
604 !< Add qnm contributions to matrix equations
605 subroutine dfw_qnm_fc_nr(this, kiter, matrix_sln, idxglo, rhs, stage, stage_old)
606 ! modules
608 ! dummy
609 class(swfdfwtype) :: this !< this instance
610 integer(I4B) :: kiter
611 class(matrixbasetype), pointer :: matrix_sln
612 integer(I4B), intent(in), dimension(:) :: idxglo
613 real(DP), intent(inout), dimension(:) :: rhs
614 real(DP), intent(inout), dimension(:) :: stage
615 real(DP), intent(inout), dimension(:) :: stage_old
616 ! local
617 integer(I4B) :: n, m, ii, idiag
618 real(DP) :: qnm
619 real(DP) :: qeps
620 real(DP) :: eps
621 real(DP) :: derv
622
623 ! Calculate conductance and put into amat
624 do n = 1, this%dis%nodes
625
626 ! Find diagonal position for row n
627 idiag = this%dis%con%ia(n)
628
629 ! Loop through connections adding matrix terms
630 do ii = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
631
632 ! skip for masked cells
633 if (this%dis%con%mask(ii) == 0) cycle
634
635 ! connection variables
636 m = this%dis%con%ja(ii)
637
638 ! Fill the qnm term on the right-hand side
639 qnm = this%qcalc(n, m, stage(n), stage(m), ii)
640 rhs(n) = rhs(n) - qnm
641
642 ! Derivative calculation and fill of n terms
643 eps = get_perturbation(stage(n))
644 qeps = this%qcalc(n, m, stage(n) + eps, stage(m), ii)
645 derv = (qeps - qnm) / eps
646 call matrix_sln%add_value_pos(idxglo(idiag), derv)
647 rhs(n) = rhs(n) + derv * stage(n)
648
649 ! Derivative calculation and fill of m terms
650 eps = get_perturbation(stage(m))
651 qeps = this%qcalc(n, m, stage(n), stage(m) + eps, ii)
652 derv = (qeps - qnm) / eps
653 call matrix_sln%add_value_pos(idxglo(ii), derv)
654 rhs(n) = rhs(n) + derv * stage(m)
655
656 end do
657 end do
658
659 end subroutine dfw_qnm_fc_nr
660
661 !> @brief fill newton
662 !<
663 subroutine dfw_fn(this, kiter, matrix_sln, idxglo, rhs, stage)
664 ! dummy
665 class(swfdfwtype) :: this !< this instance
666 integer(I4B) :: kiter
667 class(matrixbasetype), pointer :: matrix_sln
668 integer(I4B), intent(in), dimension(:) :: idxglo
669 real(DP), intent(inout), dimension(:) :: rhs
670 real(DP), intent(inout), dimension(:) :: stage
671 ! local
672
673 ! add newton terms to solution matrix
674 ! todo: add newton terms here instead?
675 ! this routine is probably not necessary as method is fully newton
676
677 end subroutine dfw_fn
678
679 !> @brief calculate flow between cells n and m
680 !<
681 function qcalc(this, n, m, stage_n, stage_m, ipos) result(qnm)
682 ! dummy
683 class(swfdfwtype) :: this !< this instance
684 integer(I4B), intent(in) :: n !< number for cell n
685 integer(I4B), intent(in) :: m !< number for cell m
686 real(dp), intent(in) :: stage_n !< stage in reach n
687 real(dp), intent(in) :: stage_m !< stage in reach m
688 integer(I4B), intent(in) :: ipos !< connection number
689 ! local
690 integer(I4B) :: isympos
691 real(dp) :: qnm
692 real(dp) :: cond
693 real(dp) :: cl1
694 real(dp) :: cl2
695
696 ! Set connection lengths
697 isympos = this%dis%con%jas(ipos)
698 if (n < m) then
699 cl1 = this%dis%con%cl1(isympos)
700 cl2 = this%dis%con%cl2(isympos)
701 else
702 cl1 = this%dis%con%cl2(isympos)
703 cl2 = this%dis%con%cl1(isympos)
704 end if
705
706 ! Calculate conductance
707 if (this%iswrcond == 0) then
708 cond = this%get_cond(n, m, ipos, stage_n, stage_m, cl1, cl2)
709 else if (this%iswrcond == 1) then
710 cond = this%get_cond_swr(n, m, ipos, stage_n, stage_m, cl1, cl2)
711 end if
712
713 ! calculate flow between n and m
714 qnm = cond * (stage_m - stage_n)
715
716 end function qcalc
717
718 !> @brief calculate effective conductance between cells n and m
719 !!
720 !! Calculate half-cell conductances for cell n and cell m and then use
721 !! harmonic averaging to calculate the effective conductance between the
722 !< two cells.
723 function get_cond(this, n, m, ipos, stage_n, stage_m, cln, clm) result(cond)
724 ! modules
725 use smoothingmodule, only: squadratic
726 ! dummy
727 class(swfdfwtype) :: this !< this instance
728 integer(I4B), intent(in) :: n !< number for cell n
729 integer(I4B), intent(in) :: m !< number for cell m
730 integer(I4B), intent(in) :: ipos !< connection number
731 real(dp), intent(in) :: stage_n !< stage in reach n
732 real(dp), intent(in) :: stage_m !< stage in reach m
733 real(dp), intent(in) :: cln !< distance from cell n to shared face with m
734 real(dp), intent(in) :: clm !< distance from cell m to shared face with n
735 ! local
736 real(dp) :: depth_n
737 real(dp) :: depth_m
738 real(dp) :: dhds_n
739 real(dp) :: dhds_m
740 real(dp) :: width_n
741 real(dp) :: width_m
742 real(dp) :: range = 1.d-6
743 real(dp) :: dydx
744 real(dp) :: smooth_factor
745 real(dp) :: length_nm
746 real(dp) :: cond
747 real(dp) :: cn
748 real(dp) :: cm
749
750 ! we are using a harmonic conductance approach here; however
751 ! the SWR Process for MODFLOW-2005/NWT uses length-weighted
752 ! average areas and hydraulic radius instead.
753 length_nm = cln + clm
754 cond = dzero
755 if (length_nm > dprec) then
756
757 ! Calculate depth in each reach
758 depth_n = stage_n - this%dis%bot(n)
759 depth_m = stage_m - this%dis%bot(m)
760
761 ! assign gradients
762 if (this%is2d == 0) then
763 dhds_n = abs(stage_m - stage_n) / (cln + clm)
764 dhds_m = dhds_n
765 else
766 dhds_n = this%grad_dhds_mag(n)
767 dhds_m = this%grad_dhds_mag(m)
768 end if
769
770 ! Assign upstream depth, if not central
771 if (this%icentral == 0) then
772 ! use upstream weighting
773 if (stage_n > stage_m) then
774 depth_m = depth_n
775 else
776 depth_n = depth_m
777 end if
778 end if
779
780 ! Calculate a smoothed depth that goes to zero over
781 ! the specified range
782 call squadratic(depth_n, range, dydx, smooth_factor)
783 depth_n = depth_n * smooth_factor
784 call squadratic(depth_m, range, dydx, smooth_factor)
785 depth_m = depth_m * smooth_factor
786
787 ! Get the flow widths for n and m from dis package
788 call this%dis%get_flow_width(n, m, ipos, width_n, width_m)
789
790 ! Calculate half-cell conductance for reach
791 ! n and m
792 cn = this%get_cond_n(n, depth_n, cln, width_n, dhds_n)
793 cm = this%get_cond_n(m, depth_m, clm, width_m, dhds_m)
794
795 ! Use harmonic mean to calculate weighted
796 ! conductance between the centers of reaches
797 ! n and m
798 if ((cn + cm) > dprec) then
799 cond = cn * cm / (cn + cm)
800 else
801 cond = dzero
802 end if
803
804 end if
805
806 end function get_cond
807
808 !> @brief Calculate half cell conductance
809 !!
810 !! Calculate half-cell conductance for cell n
811 !! using conveyance and Manning equation
812 function get_cond_n(this, n, depth, dx, width, dhds) result(c)
813 ! modules
814 ! dummy
815 class(swfdfwtype) :: this !< this instance
816 integer(I4B), intent(in) :: n !< reach number
817 real(dp), intent(in) :: depth !< simulated depth (stage - elevation) in reach n for this iteration
818 real(dp), intent(in) :: dx !< half-cell distance
819 real(dp), intent(in) :: width !< width of the reach perpendicular to flow
820 real(dp), intent(in) :: dhds !< gradient
821 ! return
822 real(dp) :: c
823 ! local
824 real(dp) :: rough
825 real(dp) :: dhds_sqr
826 real(dp) :: conveyance
827
828 ! Calculate conveyance, which is a * r**DTWOTHIRDS / roughc
829 rough = this%manningsn(n)
830 conveyance = this%cxs%get_conveyance(this%idcxs(n), width, depth, rough)
831 dhds_sqr = dhds**dhalf
832 if (dhds_sqr < dem10) then
833 dhds_sqr = dem10
834 end if
835
836 ! Multiply by unitconv and divide conveyance by sqrt of friction slope and dx
837 c = this%unitconv * conveyance / dx / dhds_sqr
838
839 end function get_cond_n
840
841 !> @brief Calculate effective conductance for cells n and m using SWR method
842 !!
843 !! The SWR Process for MODFLOW uses average cell parameters from cell n and
844 !! m to calculate an effective conductance. This is different from the
845 !! default approach used in SWF, which uses harmonic averaging on two half-
846 !< cell conductances.
847 function get_cond_swr(this, n, m, ipos, stage_n, stage_m, cln, clm) result(cond)
848 ! modules
849 use smoothingmodule, only: squadratic
850 ! dummy
851 class(swfdfwtype) :: this !< this instance
852 integer(I4B), intent(in) :: n !< number for cell n
853 integer(I4B), intent(in) :: m !< number for cell m
854 integer(I4B), intent(in) :: ipos !< connection number
855 real(dp), intent(in) :: stage_n !< stage in reach n
856 real(dp), intent(in) :: stage_m !< stage in reach m
857 real(dp), intent(in) :: cln !< distance from cell n to shared face with m
858 real(dp), intent(in) :: clm !< distance from cell m to shared face with n
859 ! local
860 real(dp) :: depth_n
861 real(dp) :: depth_m
862 real(dp) :: dhds_n
863 real(dp) :: dhds_m
864 real(dp) :: dhds_nm
865 real(dp) :: dhds_sqr
866 real(dp) :: width_n
867 real(dp) :: width_m
868 real(dp) :: range = 1.d-6
869 real(dp) :: dydx
870 real(dp) :: smooth_factor
871 real(dp) :: length_nm
872 real(dp) :: cond
873 real(dp) :: ravg
874 real(dp) :: rinv_avg
875 real(dp) :: area_n, area_m, area_avg
876 real(dp) :: rhn, rhm, rhavg
877 real(dp) :: weight_n
878 real(dp) :: weight_m
879 real(dp) :: rough_n
880 real(dp) :: rough_m
881
882 ! Use harmonic weighting for 1/manningsn, but using length-weighted
883 ! averaging for other terms
884 length_nm = cln + clm
885 cond = dzero
886 if (length_nm > dprec) then
887
888 ! Calculate depth in each reach
889 depth_n = stage_n - this%dis%bot(n)
890 depth_m = stage_m - this%dis%bot(m)
891
892 ! Assign upstream depth, if not central
893 if (this%icentral == 0) then
894 ! use upstream weighting
895 if (stage_n > stage_m) then
896 depth_m = depth_n
897 else
898 depth_n = depth_m
899 end if
900 end if
901
902 ! Calculate a smoothed depth that goes to zero over
903 ! the specified range
904 call squadratic(depth_n, range, dydx, smooth_factor)
905 depth_n = depth_n * smooth_factor
906 call squadratic(depth_m, range, dydx, smooth_factor)
907 depth_m = depth_m * smooth_factor
908
909 ! Get the flow widths for n and m from dis package
910 call this%dis%get_flow_width(n, m, ipos, width_n, width_m)
911
912 ! linear weight toward node closer to shared face
913 weight_n = clm / length_nm
914 weight_m = done - weight_n
915
916 ! average cross sectional flow area
917 area_n = this%cxs%get_area(this%idcxs(n), width_n, depth_n)
918 area_m = this%cxs%get_area(this%idcxs(m), width_m, depth_m)
919 area_avg = weight_n * area_n + weight_m * area_m
920
921 ! average hydraulic radius
922 if (this%is2d == 0) then
923 rhn = this%cxs%get_hydraulic_radius(this%idcxs(n), width_n, &
924 depth_n, area_n)
925 rhm = this%cxs%get_hydraulic_radius(this%idcxs(m), width_m, &
926 depth_m, area_m)
927 rhavg = weight_n * rhn + weight_m * rhm
928 else
929 rhavg = area_avg / width_n
930 end if
931 rhavg = rhavg**dtwothirds
932
933 ! average gradient
934 if (this%is2d == 0) then
935 dhds_nm = abs(stage_m - stage_n) / (length_nm)
936 else
937 dhds_n = this%grad_dhds_mag(n)
938 dhds_m = this%grad_dhds_mag(m)
939 dhds_nm = weight_n * dhds_n + weight_m * dhds_m
940 end if
941 dhds_sqr = dhds_nm**dhalf
942 if (dhds_sqr < dem10) then
943 dhds_sqr = dem10
944 end if
945
946 ! weighted harmonic mean for inverse mannings value
947 weight_n = cln / length_nm
948 weight_m = done - weight_n
949 rough_n = this%cxs%get_roughness(this%idcxs(n), width_n, depth_n, &
950 this%manningsn(n), dhds_nm)
951 rough_m = this%cxs%get_roughness(this%idcxs(m), width_m, depth_m, &
952 this%manningsn(m), dhds_nm)
953 ravg = (weight_n + weight_m) / &
954 (weight_n / rough_n + weight_m / rough_m)
955 rinv_avg = done / ravg
956
957 ! calculate conductance using averaged values
958 cond = this%unitconv * rinv_avg * area_avg * rhavg / dhds_sqr / length_nm
959
960 end if
961
962 end function get_cond_swr
963
964 !> @brief Calculate flow area between cell n and m
965 !!
966 !! Calculate an average flow area between cell n and m.
967 !! First calculate a flow area for cell n and then for
968 !! cell m and linearly weight the areas using the connection
969 !< distances.
970 function get_flow_area_nm(this, n, m, stage_n, stage_m, cln, clm, &
971 ipos) result(area_avg)
972 ! module
973 use smoothingmodule, only: squadratic
974 ! dummy
975 class(swfdfwtype) :: this !< this instance
976 integer(I4B), intent(in) :: n
977 integer(I4B), intent(in) :: m
978 real(dp), intent(in) :: stage_n
979 real(dp), intent(in) :: stage_m
980 real(dp), intent(in) :: cln
981 real(dp), intent(in) :: clm
982 integer(I4B), intent(in) :: ipos
983 ! local
984 real(dp) :: depth_n
985 real(dp) :: depth_m
986 real(dp) :: width_n
987 real(dp) :: width_m
988 real(dp) :: area_n
989 real(dp) :: area_m
990 real(dp) :: weight_n
991 real(dp) :: weight_m
992 real(dp) :: length_nm
993 real(dp) :: range = 1.d-6
994 real(dp) :: dydx
995 real(dp) :: smooth_factor
996 ! return
997 real(dp) :: area_avg
998
999 ! depths
1000 depth_n = stage_n - this%dis%bot(n)
1001 depth_m = stage_m - this%dis%bot(m)
1002
1003 ! Assign upstream depth, if not central
1004 if (this%icentral == 0) then
1005 ! use upstream weighting
1006 if (stage_n > stage_m) then
1007 depth_m = depth_n
1008 else
1009 depth_n = depth_m
1010 end if
1011 end if
1012
1013 ! Calculate a smoothed depth that goes to zero over
1014 ! the specified range
1015 call squadratic(depth_n, range, dydx, smooth_factor)
1016 depth_n = depth_n * smooth_factor
1017 call squadratic(depth_m, range, dydx, smooth_factor)
1018 depth_m = depth_m * smooth_factor
1019
1020 ! Get the flow widths for n and m from dis package
1021 call this%dis%get_flow_width(n, m, ipos, width_n, width_m)
1022
1023 ! linear weight toward node closer to shared face
1024 length_nm = cln + clm
1025 weight_n = clm / length_nm
1026 weight_m = done - weight_n
1027
1028 ! average cross sectional flow area
1029 area_n = this%cxs%get_area(this%idcxs(n), width_n, depth_n)
1030 area_m = this%cxs%get_area(this%idcxs(m), width_m, depth_m)
1031 area_avg = weight_n * area_n + weight_m * area_m
1032
1033 end function get_flow_area_nm
1034
1035 !> @brief Calculate average hydraulic gradient magnitude for each cell
1036 !!
1037 !! Go through each cell and calculate the average hydraulic gradient using
1038 !! an xt3d-style gradient interpolation. This is used for 2D grids in the
1039 !! calculation of an effective conductance. For 1D grids, gradients are
1040 !< calculated between cell centers.
1041 subroutine calc_dhds(this)
1042 ! modules
1044 ! dummy
1045 class(swfdfwtype) :: this !< this instance
1046 ! local
1047 integer(I4B) :: n
1048 integer(I4B) :: m
1049 integer(I4B) :: ipos
1050 integer(I4B) :: isympos
1051 real(DP) :: cl1
1052 real(DP) :: cl2
1053
1054 do n = 1, this%dis%nodes
1055 this%grad_dhds_mag(n) = dzero
1056 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
1057 m = this%dis%con%ja(ipos)
1058 isympos = this%dis%con%jas(ipos)
1059
1060 ! determine cl1 and cl2
1061 if (n < m) then
1062 cl1 = this%dis%con%cl1(isympos)
1063 cl2 = this%dis%con%cl2(isympos)
1064 else
1065 cl1 = this%dis%con%cl2(isympos)
1066 cl2 = this%dis%con%cl1(isympos)
1067 end if
1068
1069 ! store for n < m in upper right triangular part of symmetric dhdsja array
1070 if (n < m) then
1071 if (cl1 + cl2 > dprec) then
1072 this%dhdsja(isympos) = (this%hnew(m) - this%hnew(n)) / (cl1 + cl2)
1073 else
1074 this%dhdsja(isympos) = dzero
1075 end if
1076 end if
1077 end do
1078 end do
1079
1080 ! pass dhdsja into the vector interpolation to get the components
1081 ! of the gradient at the cell center
1082 call vector_interpolation_2d(this%dis, this%dhdsja, vmag=this%grad_dhds_mag)
1083
1084 end subroutine calc_dhds
1085
1086 !> @ brief Newton under relaxation
1087 !!
1088 !< If stage is below the bottom, then pull it up a bit
1089 subroutine dfw_nur(this, neqmod, x, xtemp, dx, inewtonur, dxmax, locmax)
1090 ! dummy
1091 class(swfdfwtype) :: this !< this instance
1092 integer(I4B), intent(in) :: neqmod !< number of equations
1093 real(DP), dimension(neqmod), intent(inout) :: x !< dependent variable
1094 real(DP), dimension(neqmod), intent(in) :: xtemp !< temporary dependent variable
1095 real(DP), dimension(neqmod), intent(inout) :: dx !< change in dependent variable
1096 integer(I4B), intent(inout) :: inewtonur !< flag to indication relaxation was applied
1097 real(DP), intent(inout) :: dxmax !< max change in x
1098 integer(I4B), intent(inout) :: locmax !< location of max change
1099 ! local
1100 integer(I4B) :: n
1101 real(DP) :: botm
1102 real(DP) :: xx
1103 real(DP) :: dxx
1104
1105 ! Newton-Raphson under-relaxation
1106 do n = 1, this%dis%nodes
1107 if (this%ibound(n) < 1) cycle
1108 if (this%icelltype(n) > 0) then
1109 botm = this%dis%bot(n)
1110 ! only apply Newton-Raphson under-relaxation if
1111 ! solution head is below the bottom of the model
1112 if (x(n) < botm) then
1113 inewtonur = 1
1114 xx = xtemp(n) * (done - dp9) + botm * dp9
1115 dxx = x(n) - xx
1116 if (abs(dxx) > abs(dxmax)) then
1117 locmax = n
1118 dxmax = dxx
1119 end if
1120 x(n) = xx
1121 dx(n) = dzero
1122 end if
1123 end if
1124 end do
1125
1126 end subroutine dfw_nur
1127
1128 !> @ brief Calculate flow for each connection and store in flowja
1129 !<
1130 subroutine dfw_cq(this, stage, stage_old, flowja)
1131 ! dummy
1132 class(swfdfwtype) :: this !< this instance
1133 real(DP), intent(inout), dimension(:) :: stage !< calculated head
1134 real(DP), intent(inout), dimension(:) :: stage_old !< calculated head from previous time step
1135 real(DP), intent(inout), dimension(:) :: flowja !< vector of flows in CSR format
1136 ! local
1137 integer(I4B) :: n, ipos, m
1138 real(DP) :: qnm
1139
1140 do n = 1, this%dis%nodes
1141 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
1142 m = this%dis%con%ja(ipos)
1143 if (m < n) cycle
1144 qnm = this%qcalc(n, m, stage(n), stage(m), ipos)
1145 flowja(ipos) = qnm
1146 flowja(this%dis%con%isym(ipos)) = -qnm
1147 end do
1148 end do
1149
1150 end subroutine dfw_cq
1151
1152 !> @ brief Model budget calculation for package
1153 !<
1154 subroutine dfw_bd(this, isuppress_output, model_budget)
1155 ! modules
1156 use budgetmodule, only: budgettype
1157 ! dummy variables
1158 class(swfdfwtype) :: this !< this instance
1159 integer(I4B), intent(in) :: isuppress_output !< flag to suppress model output
1160 type(budgettype), intent(inout) :: model_budget !< model budget object
1161
1162 ! Add any DFW budget terms
1163 ! none
1164
1165 end subroutine dfw_bd
1166
1167 !> @ brief save flows for package
1168 !<
1169 subroutine dfw_save_model_flows(this, flowja, icbcfl, icbcun)
1170 ! dummy
1171 class(swfdfwtype) :: this !< this instance
1172 real(DP), dimension(:), intent(in) :: flowja !< vector of flows in CSR format
1173 integer(I4B), intent(in) :: icbcfl !< flag to indicate if flows should be saved
1174 integer(I4B), intent(in) :: icbcun !< unit number for flow output
1175 ! local
1176 integer(I4B) :: ibinun
1177
1178 ! Set unit number for binary output
1179 if (this%ipakcb < 0) then
1180 ibinun = icbcun
1181 elseif (this%ipakcb == 0) then
1182 ibinun = 0
1183 else
1184 ibinun = this%ipakcb
1185 end if
1186 if (icbcfl == 0) ibinun = 0
1187
1188 ! Write the face flows if requested
1189 if (ibinun /= 0) then
1190 ! flowja
1191 call this%dis%record_connection_array(flowja, ibinun, this%iout)
1192 end if
1193
1194 ! Calculate velocities at cell centers and write, if requested
1195 if (this%isavvelocity /= 0) then
1196 if (ibinun /= 0) call this%sav_velocity(ibinun)
1197 end if
1198
1199 end subroutine dfw_save_model_flows
1200
1201 !> @ brief print flows for package
1202 !<
1203 subroutine dfw_print_model_flows(this, ibudfl, flowja)
1204 ! modules
1205 use tdismodule, only: kper, kstp
1206 use constantsmodule, only: lenbigline
1207 ! dummy
1208 class(swfdfwtype) :: this !< this instance
1209 integer(I4B), intent(in) :: ibudfl !< print flag
1210 real(DP), intent(inout), dimension(:) :: flowja !< vector of flows in CSR format
1211 ! local
1212 character(len=LENBIGLINE) :: line
1213 character(len=30) :: tempstr
1214 integer(I4B) :: n, ipos, m
1215 real(DP) :: qnm
1216 ! formats
1217 character(len=*), parameter :: fmtiprflow = &
1218 &"(/,4x,'CALCULATED INTERCELL FLOW FOR PERIOD ', i0, ' STEP ', i0)"
1219
1220 ! Write flowja to list file if requested
1221 if (ibudfl /= 0 .and. this%iprflow > 0) then
1222 write (this%iout, fmtiprflow) kper, kstp
1223 do n = 1, this%dis%nodes
1224 line = ''
1225 call this%dis%noder_to_string(n, tempstr)
1226 line = trim(tempstr)//':'
1227 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
1228 m = this%dis%con%ja(ipos)
1229 call this%dis%noder_to_string(m, tempstr)
1230 line = trim(line)//' '//trim(tempstr)
1231 qnm = flowja(ipos)
1232 write (tempstr, '(1pg15.6)') qnm
1233 line = trim(line)//' '//trim(adjustl(tempstr))
1234 end do
1235 write (this%iout, '(a)') trim(line)
1236 end do
1237 end if
1238
1239 end subroutine dfw_print_model_flows
1240
1241 !> @brief deallocate memory
1242 !<
1243 subroutine dfw_da(this)
1244 ! modules
1248 ! dummy
1249 class(swfdfwtype) :: this !< this instance
1250
1251 ! Deallocate input memory
1252 call memorystore_remove(this%name_model, 'DFW', idm_context)
1253
1254 ! Deallocate arrays
1255 call mem_deallocate(this%manningsn)
1256 call mem_deallocate(this%idcxs)
1257 call mem_deallocate(this%icelltype)
1258 call mem_deallocate(this%nodedge)
1259 call mem_deallocate(this%ihcedge)
1260 call mem_deallocate(this%propsedge)
1261 call mem_deallocate(this%vcomp)
1262 call mem_deallocate(this%vmag)
1263 if (this%is2d == 1) then
1264 call mem_deallocate(this%grad_dhds_mag)
1265 call mem_deallocate(this%dhdsja)
1266 end if
1267
1268 ! Scalars
1269 call mem_deallocate(this%is2d)
1270 call mem_deallocate(this%icentral)
1271 call mem_deallocate(this%iswrcond)
1272 call mem_deallocate(this%unitconv)
1273 call mem_deallocate(this%lengthconv)
1274 call mem_deallocate(this%timeconv)
1275 call mem_deallocate(this%isavvelocity)
1276 call mem_deallocate(this%icalcvelocity)
1277 call mem_deallocate(this%nedges)
1278 call mem_deallocate(this%lastedge)
1279
1280 ! obs package
1281 call mem_deallocate(this%inobspkg)
1282 call this%obs%obs_da()
1283 deallocate (this%obs)
1284 nullify (this%obs)
1285 nullify (this%cxs)
1286
1287 ! deallocate parent
1288 call this%NumericalPackageType%da()
1289
1290 ! pointers
1291 this%hnew => null()
1292
1293 end subroutine dfw_da
1294
1295 !> @brief Calculate the 3 components of velocity at the cell center
1296 !!
1297 !! todo: duplicated from NPF; should consolidate
1298 !<
1299 subroutine calc_velocity(this, flowja)
1300 ! modules
1301 ! dummy
1302 class(swfdfwtype) :: this !< this instance
1303 real(DP), intent(in), dimension(:) :: flowja !< vector of flows in CSR format
1304 ! local
1305 integer(I4B) :: n
1306 integer(I4B) :: m
1307 integer(I4B) :: ipos
1308 integer(I4B) :: isympos
1309 integer(I4B) :: ihc
1310 integer(I4B) :: ic
1311 integer(I4B) :: iz
1312 integer(I4B) :: nc
1313 integer(I4B) :: ncz
1314 real(DP) :: vx
1315 real(DP) :: vy
1316 real(DP) :: vz
1317 real(DP) :: xn
1318 real(DP) :: yn
1319 real(DP) :: zn
1320 real(DP) :: xc
1321 real(DP) :: yc
1322 real(DP) :: zc
1323 real(DP) :: cl1
1324 real(DP) :: cl2
1325 real(DP) :: dltot
1326 real(DP) :: ooclsum
1327 real(DP) :: dsumx
1328 real(DP) :: dsumy
1329 real(DP) :: dsumz
1330 real(DP) :: denom
1331 real(DP) :: area
1332 real(DP) :: axy
1333 real(DP) :: ayx
1334 real(DP), allocatable, dimension(:) :: vi
1335 real(DP), allocatable, dimension(:) :: di
1336 real(DP), allocatable, dimension(:) :: viz
1337 real(DP), allocatable, dimension(:) :: diz
1338 real(DP), allocatable, dimension(:) :: nix
1339 real(DP), allocatable, dimension(:) :: niy
1340 real(DP), allocatable, dimension(:) :: wix
1341 real(DP), allocatable, dimension(:) :: wiy
1342 real(DP), allocatable, dimension(:) :: wiz
1343 real(DP), allocatable, dimension(:) :: bix
1344 real(DP), allocatable, dimension(:) :: biy
1345 logical :: nozee = .true.
1346
1347 ! Ensure dis has necessary information
1348 ! todo: do we need this for SWF?
1349 if (this%icalcvelocity /= 0 .and. this%dis%con%ianglex == 0) then
1350 call store_error('Error. ANGLDEGX not provided in '// &
1351 'discretization file. ANGLDEGX required for '// &
1352 'calculation of velocity.', terminate=.true.)
1353 end if
1354
1355 ! Find max number of connections and allocate weight arrays
1356 nc = 0
1357 do n = 1, this%dis%nodes
1358
1359 ! Count internal model connections
1360 ic = this%dis%con%ia(n + 1) - this%dis%con%ia(n) - 1
1361
1362 ! Count edge connections
1363 do m = 1, this%nedges
1364 if (this%nodedge(m) == n) then
1365 ic = ic + 1
1366 end if
1367 end do
1368
1369 ! Set max number of connections for any cell
1370 if (ic > nc) nc = ic
1371 end do
1372
1373 ! Allocate storage arrays needed for cell-centered calculation
1374 allocate (vi(nc))
1375 allocate (di(nc))
1376 allocate (viz(nc))
1377 allocate (diz(nc))
1378 allocate (nix(nc))
1379 allocate (niy(nc))
1380 allocate (wix(nc))
1381 allocate (wiy(nc))
1382 allocate (wiz(nc))
1383 allocate (bix(nc))
1384 allocate (biy(nc))
1385
1386 ! Go through each cell and calculate specific discharge
1387 do n = 1, this%dis%nodes
1388
1389 ! first calculate geometric properties for x and y directions and
1390 ! the specific discharge at a face (vi)
1391 ic = 0
1392 iz = 0
1393 vi(:) = dzero
1394 di(:) = dzero
1395 viz(:) = dzero
1396 diz(:) = dzero
1397 nix(:) = dzero
1398 niy(:) = dzero
1399 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
1400 m = this%dis%con%ja(ipos)
1401 isympos = this%dis%con%jas(ipos)
1402 ihc = this%dis%con%ihc(isympos)
1403 ic = ic + 1
1404 call this%dis%connection_normal(n, m, ihc, xn, yn, zn, ipos)
1405 call this%dis%connection_vector(n, m, nozee, done, done, &
1406 ihc, xc, yc, zc, dltot)
1407 cl1 = this%dis%con%cl1(isympos)
1408 cl2 = this%dis%con%cl2(isympos)
1409 if (m < n) then
1410 cl1 = this%dis%con%cl2(isympos)
1411 cl2 = this%dis%con%cl1(isympos)
1412 end if
1413 ooclsum = done / (cl1 + cl2)
1414 nix(ic) = -xn
1415 niy(ic) = -yn
1416 di(ic) = dltot * cl1 * ooclsum
1417 area = this%get_flow_area_nm(n, m, this%hnew(n), this%hnew(m), &
1418 cl1, cl2, ipos)
1419 if (area > dzero) then
1420 vi(ic) = flowja(ipos) / area
1421 else
1422 vi(ic) = dzero
1423 end if
1424
1425 end do
1426
1427 ! Look through edge flows that may have been provided by an exchange
1428 ! and incorporate them into the averaging arrays
1429 do m = 1, this%nedges
1430 if (this%nodedge(m) == n) then
1431
1432 ! propsedge: (Q, area, nx, ny, distance)
1433 ihc = this%ihcedge(m)
1434 area = this%propsedge(2, m)
1435
1436 ic = ic + 1
1437 nix(ic) = -this%propsedge(3, m)
1438 niy(ic) = -this%propsedge(4, m)
1439 di(ic) = this%propsedge(5, m)
1440 if (area > dzero) then
1441 vi(ic) = this%propsedge(1, m) / area
1442 else
1443 vi(ic) = dzero
1444 end if
1445
1446 end if
1447 end do
1448
1449 ! Assign number of vertical and horizontal connections
1450 ncz = iz
1451 nc = ic
1452
1453 ! calculate z weight (wiz) and z velocity
1454 if (ncz == 1) then
1455 wiz(1) = done
1456 else
1457 dsumz = dzero
1458 do iz = 1, ncz
1459 dsumz = dsumz + diz(iz)
1460 end do
1461 denom = (ncz - done)
1462 if (denom < dzero) denom = dzero
1463 dsumz = dsumz + dem10 * dsumz
1464 do iz = 1, ncz
1465 if (dsumz > dzero) wiz(iz) = done - diz(iz) / dsumz
1466 if (denom > 0) then
1467 wiz(iz) = wiz(iz) / denom
1468 else
1469 wiz(iz) = dzero
1470 end if
1471 end do
1472 end if
1473 vz = dzero
1474 do iz = 1, ncz
1475 vz = vz + wiz(iz) * viz(iz)
1476 end do
1477
1478 ! distance-based weighting
1479 nc = ic
1480 dsumx = dzero
1481 dsumy = dzero
1482 dsumz = dzero
1483 do ic = 1, nc
1484 wix(ic) = di(ic) * abs(nix(ic))
1485 wiy(ic) = di(ic) * abs(niy(ic))
1486 dsumx = dsumx + wix(ic)
1487 dsumy = dsumy + wiy(ic)
1488 end do
1489
1490 ! Finish computing omega weights. Add a tiny bit
1491 ! to dsum so that the normalized omega weight later
1492 ! evaluates to (essentially) 1 in the case of a single
1493 ! relevant connection, avoiding 0/0.
1494 dsumx = dsumx + dem10 * dsumx
1495 dsumy = dsumy + dem10 * dsumy
1496 do ic = 1, nc
1497 wix(ic) = (dsumx - wix(ic)) * abs(nix(ic))
1498 wiy(ic) = (dsumy - wiy(ic)) * abs(niy(ic))
1499 end do
1500
1501 ! compute B weights
1502 dsumx = dzero
1503 dsumy = dzero
1504 do ic = 1, nc
1505 bix(ic) = wix(ic) * sign(done, nix(ic))
1506 biy(ic) = wiy(ic) * sign(done, niy(ic))
1507 dsumx = dsumx + wix(ic) * abs(nix(ic))
1508 dsumy = dsumy + wiy(ic) * abs(niy(ic))
1509 end do
1510 if (dsumx > dzero) dsumx = done / dsumx
1511 if (dsumy > dzero) dsumy = done / dsumy
1512 axy = dzero
1513 ayx = dzero
1514 do ic = 1, nc
1515 bix(ic) = bix(ic) * dsumx
1516 biy(ic) = biy(ic) * dsumy
1517 axy = axy + bix(ic) * niy(ic)
1518 ayx = ayx + biy(ic) * nix(ic)
1519 end do
1520
1521 ! Calculate specific discharge. The divide by zero checking below
1522 ! is problematic for cells with only one flow, such as can happen
1523 ! with triangular cells in corners. In this case, the resulting
1524 ! cell velocity will be calculated as zero. The method should be
1525 ! improved so that edge flows of zero are included in these
1526 ! calculations. But this needs to be done with consideration for LGR
1527 ! cases in which flows are submitted from an exchange.
1528 vx = dzero
1529 vy = dzero
1530 do ic = 1, nc
1531 vx = vx + (bix(ic) - axy * biy(ic)) * vi(ic)
1532 vy = vy + (biy(ic) - ayx * bix(ic)) * vi(ic)
1533 end do
1534 denom = done - axy * ayx
1535 if (denom /= dzero) then
1536 vx = vx / denom
1537 vy = vy / denom
1538 end if
1539
1540 this%vcomp(1, n) = vx
1541 this%vcomp(2, n) = vy
1542 this%vcomp(3, n) = vz
1543 this%vmag(n) = sqrt(vx**2 + vy**2 + vz**2)
1544
1545 end do
1546
1547 ! cleanup
1548 deallocate (vi)
1549 deallocate (di)
1550 deallocate (nix)
1551 deallocate (niy)
1552 deallocate (wix)
1553 deallocate (wiy)
1554 deallocate (wiz)
1555 deallocate (bix)
1556 deallocate (biy)
1557
1558 end subroutine calc_velocity
1559
1560 !> @brief Reserve space for nedges cells that have an edge on them.
1561 !!
1562 !! todo: duplicated from NPF; should consolidate
1563 !! This must be called before the swf%allocate_arrays routine, which is
1564 !< called from swf%ar.
1565 subroutine increase_edge_count(this, nedges)
1566 ! dummy
1567 class(swfdfwtype) :: this !< this instance
1568 integer(I4B), intent(in) :: nedges
1569
1570 this%nedges = this%nedges + nedges
1571
1572 end subroutine increase_edge_count
1573
1574 !> @brief Provide the swf package with edge properties
1575 !!
1576 !! todo: duplicated from NPF; should consolidate
1577 !<
1578 subroutine set_edge_properties(this, nodedge, ihcedge, q, area, nx, ny, &
1579 distance)
1580 ! dummy
1581 class(swfdfwtype) :: this !< this instance
1582 integer(I4B), intent(in) :: nodedge
1583 integer(I4B), intent(in) :: ihcedge
1584 real(DP), intent(in) :: q
1585 real(DP), intent(in) :: area
1586 real(DP), intent(in) :: nx
1587 real(DP), intent(in) :: ny
1588 real(DP), intent(in) :: distance
1589 ! local
1590 integer(I4B) :: lastedge
1591
1592 this%lastedge = this%lastedge + 1
1593 lastedge = this%lastedge
1594 this%nodedge(lastedge) = nodedge
1595 this%ihcedge(lastedge) = ihcedge
1596 this%propsedge(1, lastedge) = q
1597 this%propsedge(2, lastedge) = area
1598 this%propsedge(3, lastedge) = nx
1599 this%propsedge(4, lastedge) = ny
1600 this%propsedge(5, lastedge) = distance
1601
1602 ! If this is the last edge, then the next call must be starting a new
1603 ! edge properties assignment loop, so need to reset lastedge to 0
1604 if (this%lastedge == this%nedges) this%lastedge = 0
1605
1606 end subroutine set_edge_properties
1607
1608 !> @brief Save specific discharge in binary format to ibinun
1609 !!
1610 !! todo: should write 2d velocity; what about for 1D channel?
1611 !<
1612 subroutine sav_velocity(this, ibinun)
1613 ! dummy
1614 class(swfdfwtype) :: this !< this instance
1615 integer(I4B), intent(in) :: ibinun
1616 ! local
1617 character(len=16) :: text
1618 character(len=16), dimension(3) :: auxtxt
1619 integer(I4B) :: n
1620 integer(I4B) :: naux
1621
1622 ! Write the header
1623 text = ' DATA-VCOMP'
1624 naux = 3
1625 auxtxt(:) = [' vx', ' vy', ' vz']
1626 call this%dis%record_srcdst_list_header(text, this%name_model, &
1627 this%packName, this%name_model, &
1628 this%packName, naux, auxtxt, ibinun, &
1629 this%dis%nodes, this%iout)
1630
1631 ! Write a zero for Q, and then write qx, qy, qz as aux variables
1632 do n = 1, this%dis%nodes
1633 call this%dis%record_mf6_list_entry(ibinun, n, n, dzero, naux, &
1634 this%vcomp(:, n))
1635 end do
1636
1637 end subroutine sav_velocity
1638
1639 !> @brief Define the observation types available in the package
1640 !!
1641 !< Method to define the observation types available in the package.
1642 subroutine dfw_df_obs(this)
1643 ! dummy variables
1644 class(swfdfwtype) :: this !< this instance
1645 ! local variables
1646 integer(I4B) :: indx
1647
1648 ! Store obs type and assign procedure pointer
1649 ! for ext-outflow observation type.
1650 call this%obs%StoreObsType('ext-outflow', .true., indx)
1651 this%obs%obsData(indx)%ProcessIdPtr => dfwobsidprocessor
1652
1653 end subroutine dfw_df_obs
1654
1655 subroutine dfwobsidprocessor(obsrv, dis, inunitobs, iout)
1656 ! dummy
1657 type(observetype), intent(inout) :: obsrv
1658 class(disbasetype), intent(in) :: dis
1659 integer(I4B), intent(in) :: inunitobs
1660 integer(I4B), intent(in) :: iout
1661 ! local
1662 integer(I4B) :: n
1663 character(len=LINELENGTH) :: string
1664
1665 ! Initialize variables
1666 string = obsrv%IDstring
1667 read (string, *) n
1668
1669 if (n > 0) then
1670 obsrv%NodeNumber = n
1671 else
1672 errmsg = 'Error reading data from ID string'
1673 call store_error(errmsg)
1674 call store_error_unit(inunitobs)
1675 end if
1676
1677 end subroutine dfwobsidprocessor
1678
1679 !> @brief Save observations for the package
1680 !!
1681 !< Method to save simulated values for the package.
1682 subroutine dfw_bd_obs(this)
1683 ! dummy variables
1684 class(swfdfwtype) :: this !< this instance
1685 ! local variables
1686 integer(I4B) :: i
1687 integer(I4B) :: j
1688 integer(I4B) :: n
1689 real(DP) :: v
1690 character(len=100) :: msg
1691 type(observetype), pointer :: obsrv => null()
1692
1693 ! Write simulated values for all observations
1694 if (this%obs%npakobs > 0) then
1695 call this%obs%obs_bd_clear()
1696 do i = 1, this%obs%npakobs
1697 obsrv => this%obs%pakobs(i)%obsrv
1698 do j = 1, obsrv%indxbnds_count
1699 n = obsrv%indxbnds(j)
1700 v = dzero
1701 select case (obsrv%ObsTypeId)
1702 case default
1703 msg = 'Unrecognized observation type: '//trim(obsrv%ObsTypeId)
1704 call store_error(msg)
1705 end select
1706 call this%obs%SaveOneSimval(obsrv, v)
1707 end do
1708 end do
1709
1710 ! write summary of package error messages
1711 if (count_errors() > 0) then
1712 call store_error_filename(this%input_fname)
1713 end if
1714 end if
1715
1716 end subroutine dfw_bd_obs
1717
1718 !> @brief Read and prepare observations for a package
1719 !!
1720 !< Method to read and prepare observations for a package.
1721 subroutine dfw_rp_obs(this)
1722 ! modules
1723 use tdismodule, only: kper
1724 ! dummy
1725 class(swfdfwtype), intent(inout) :: this !< this instance
1726 ! local
1727 integer(I4B) :: i
1728 integer(I4B) :: j
1729 integer(I4B) :: nn1
1730 class(observetype), pointer :: obsrv => null()
1731
1732 ! process each package observation
1733 ! only done the first stress period since boundaries are fixed
1734 ! for the simulation
1735 if (kper == 1) then
1736 do i = 1, this%obs%npakobs
1737 obsrv => this%obs%pakobs(i)%obsrv
1738
1739 ! get node number 1
1740 nn1 = obsrv%NodeNumber
1741 if (nn1 < 1 .or. nn1 > this%dis%nodes) then
1742 write (errmsg, '(a,1x,a,1x,i0,1x,a,1x,i0,a)') &
1743 trim(adjustl(obsrv%ObsTypeId)), &
1744 'reach must be greater than 0 and less than or equal to', &
1745 this%dis%nodes, '(specified value is ', nn1, ')'
1746 call store_error(errmsg)
1747 else
1748 if (obsrv%indxbnds_count == 0) then
1749 call obsrv%AddObsIndex(nn1)
1750 else
1751 errmsg = 'Programming error in dfw_rp_obs'
1752 call store_error(errmsg)
1753 end if
1754 end if
1755
1756 ! check that node number 1 is valid; call store_error if not
1757 do j = 1, obsrv%indxbnds_count
1758 nn1 = obsrv%indxbnds(j)
1759 if (nn1 < 1 .or. nn1 > this%dis%nodes) then
1760 write (errmsg, '(a,1x,a,1x,i0,1x,a,1x,i0,a)') &
1761 trim(adjustl(obsrv%ObsTypeId)), &
1762 'reach must be greater than 0 and less than or equal to', &
1763 this%dis%nodes, '(specified value is ', nn1, ')'
1764 call store_error(errmsg)
1765 end if
1766 end do
1767 end do
1768
1769 ! evaluate if there are any observation errors
1770 if (count_errors() > 0) then
1771 call store_error_filename(this%input_fname)
1772 end if
1773
1774 end if
1775
1776 end subroutine dfw_rp_obs
1777
1778end module swfdfwmodule
subroutine allocate_scalars(this, name_model, input_mempath)
Allocate and initialize scalar variables.
subroutine allocate_arrays(this)
Allocate and initialize arrays.
This module contains the BudgetModule.
Definition Budget.f90:20
This module contains simulation constants.
Definition Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition Constants.f90:45
real(dp), parameter dtwothirds
real constant 2/3
Definition Constants.f90:70
real(dp), parameter dp9
real constant 9/10
Definition Constants.f90:72
real(dp), parameter dem10
real constant 1e-10
real(dp), parameter donethird
real constant 1/3
Definition Constants.f90:67
integer(i4b), parameter lenbigline
maximum length of a big line
Definition Constants.f90:15
real(dp), parameter dhalf
real constant 1/2
Definition Constants.f90:68
real(dp), parameter dzero
real constant zero
Definition Constants.f90:65
real(dp), parameter dprec
real constant machine precision
real(dp), parameter dtwo
real constant 2
Definition Constants.f90:79
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition Constants.f90:27
real(dp), parameter done
real constant 1
Definition Constants.f90:76
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
This module defines variable data types.
Definition kind.f90:8
real(dp) function, public get_perturbation(x)
Calculate a numerical perturbation given the value of x.
Definition MathUtil.f90:372
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
subroutine, public memorystore_remove(component, subcomponent, context)
subroutine, public memorystore_release(varname, memory_path)
Release a single variable from the memory store.
subroutine, public get_isize(name, mem_path, isize)
@ brief Get the number of elements for this variable
This module contains the base numerical package type.
This module contains the derived types ObserveType and ObsDataType.
Definition Observe.f90:15
This module contains the derived type ObsType.
Definition Obs.f90:127
subroutine, public obs_cr(obs, inobs)
@ brief Create a new ObsType object
Definition Obs.f90:225
This module contains simulation methods.
Definition Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition Sim.f90:59
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition Sim.f90:204
subroutine, public store_error_unit(iunit, terminate)
Store the file unit number.
Definition Sim.f90:169
This module contains simulation variables.
character(len=maxcharlen) errmsg
error message string
character(len=linelength) idm_context
subroutine squadratic(x, range, dydx, y)
@ brief sQuadratic
subroutine source_options(this)
Copy options from IDM into package.
Definition swf-cxs.f90:176
subroutine log_options(this, found)
Write user options to list file.
Definition swf-cxs.f90:202
integer(i4b), pointer, public kstp
current time step number
Definition tdis.f90:27
integer(i4b), pointer, public kper
current stress period number
Definition tdis.f90:26
subroutine, public vector_interpolation_2d(dis, flowja, nedges, nodedge, propsedge, vcomp, vmag, flowareaja)
Interpolate 2D vector components at cell center.
Derived type for the Budget object.
Definition Budget.f90:40
This class is used to store a single deferred-length character string. It was designed to work in an ...
flags indicating which DFW griddata were found in the input
Definition swf-dfw.f90:42
flags indicating which DFW options were found in the input
Definition swf-dfw.f90:30
subroutine sav_velocity(this, ibinun)
Save specific discharge in binary format to ibinun.
Definition swf-dfw.f90:1613
subroutine dfw_bd_obs(this)
Save observations for the package.
Definition swf-dfw.f90:1683
subroutine calc_velocity(this, flowja)
Calculate the 3 components of velocity at the cell center.
Definition swf-dfw.f90:1300
subroutine dfw_ar(this, ibound, hnew)
allocate memory
Definition swf-dfw.f90:521
real(dp) function get_flow_area_nm(this, n, m, stage_n, stage_m, cln, clm, ipos)
Calculate flow area between cell n and m.
Definition swf-dfw.f90:972
subroutine dfw_print_model_flows(this, ibudfl, flowja)
@ brief print flows for package
Definition swf-dfw.f90:1204
subroutine dfw_save_model_flows(this, flowja, icbcfl, icbcun)
@ brief save flows for package
Definition swf-dfw.f90:1170
subroutine write_cxs_tables(this)
Definition swf-dfw.f90:501
subroutine dfw_rp_obs(this)
Read and prepare observations for a package.
Definition swf-dfw.f90:1722
subroutine dfw_bd(this, isuppress_output, model_budget)
@ brief Model budget calculation for package
Definition swf-dfw.f90:1155
subroutine dfwobsidprocessor(obsrv, dis, inunitobs, iout)
Definition swf-dfw.f90:1656
subroutine increase_edge_count(this, nedges)
Reserve space for nedges cells that have an edge on them.
Definition swf-dfw.f90:1566
subroutine calc_dhds(this)
Calculate average hydraulic gradient magnitude for each cell.
Definition swf-dfw.f90:1042
subroutine dfw_fc(this, kiter, matrix_sln, idxglo, rhs, stage, stage_old)
fill coefficients
Definition swf-dfw.f90:581
subroutine dfw_cr(dfwobj, name_model, input_mempath, inunit, iout, cxs)
create package
Definition swf-dfw.f90:128
subroutine source_griddata(this)
copy griddata from IDM to package
Definition swf-dfw.f90:437
subroutine dfw_nur(this, neqmod, x, xtemp, dx, inewtonur, dxmax, locmax)
@ brief Newton under relaxation
Definition swf-dfw.f90:1090
subroutine dfw_cq(this, stage, stage_old, flowja)
@ brief Calculate flow for each connection and store in flowja
Definition swf-dfw.f90:1131
subroutine dfw_df(this, dis)
load data from IDM to package
Definition swf-dfw.f90:181
subroutine dfw_fn(this, kiter, matrix_sln, idxglo, rhs, stage)
fill newton
Definition swf-dfw.f90:664
real(dp) function get_cond(this, n, m, ipos, stage_n, stage_m, cln, clm)
calculate effective conductance between cells n and m
Definition swf-dfw.f90:724
subroutine dfw_qnm_fc_nr(this, kiter, matrix_sln, idxglo, rhs, stage, stage_old)
fill coefficients
Definition swf-dfw.f90:606
subroutine log_griddata(this, found)
log griddata to list file
Definition swf-dfw.f90:481
subroutine dfw_load(this)
load data from IDM to package
Definition swf-dfw.f90:298
real(dp) function get_cond_swr(this, n, m, ipos, stage_n, stage_m, cln, clm)
Calculate effective conductance for cells n and m using SWR method.
Definition swf-dfw.f90:848
subroutine dfw_ad(this, irestore)
advance
Definition swf-dfw.f90:566
subroutine dfw_df_obs(this)
Define the observation types available in the package.
Definition swf-dfw.f90:1643
real(dp) function qcalc(this, n, m, stage_n, stage_m, ipos)
calculate flow between cells n and m
Definition swf-dfw.f90:682
subroutine dfw_da(this)
deallocate memory
Definition swf-dfw.f90:1244
real(dp) function get_cond_n(this, n, depth, dx, width, dhds)
Calculate half cell conductance.
Definition swf-dfw.f90:813
subroutine set_edge_properties(this, nodedge, ihcedge, q, area, nx, ny, distance)
Provide the swf package with edge properties.
Definition swf-dfw.f90:1580
subroutine dfw_rp(this)
allocate memory
Definition swf-dfw.f90:554