@@ -13,6 +13,7 @@ module EDPatchDynamicsMod
1313 use EDTypesMod , only : maxPatchesPerSite_by_disttype
1414 use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type
1515 use EDTypesMod , only : min_patch_area
16+ use EDTypesMod , only : min_patch_area_forced
1617 use EDTypesMod , only : nclmax
1718 use EDTypesMod , only : maxpft
1819 use EDTypesMod , only : dtype_ifall
@@ -2058,16 +2059,28 @@ subroutine terminate_patches(currentSite)
20582059 type (ed_patch_type), pointer :: currentPatch
20592060 type (ed_patch_type), pointer :: olderPatch
20602061 type (ed_patch_type), pointer :: youngerPatch
2062+ integer , parameter :: max_cycles = 10 ! After 10 loops through
2063+ ! You should had fused
2064+ integer :: count_cycles
20612065
20622066 real (r8 ) areatot ! variable for checking whether the total patch area is wrong.
20632067 !- --------------------------------------------------------------------
20642068
2069+ count_cycles = 0
2070+
20652071 currentPatch = > currentSite% youngest_patch
20662072 do while (associated (currentPatch))
20672073
20682074 if (currentPatch% area <= min_patch_area)then
20692075
2070- if ( .not. associated (currentPatch,currentSite% youngest_patch) ) then
2076+ ! Even if the patch area is small, avoid fusing it into its neighbor
2077+ ! if it is the youngest of all patches. We do this in attempts to maintain
2078+ ! a discrete patch for very young patches
2079+ ! However, if the patch to be fused is excessivlely small, then fuse
2080+ ! at all costs. If it is not fused, it will make
2081+
2082+ if ( .not. associated (currentPatch,currentSite% youngest_patch) .or. &
2083+ currentPatch% area <= min_patch_area_forced ) then
20712084
20722085 if (associated (currentPatch% older) )then
20732086
@@ -2088,12 +2101,12 @@ subroutine terminate_patches(currentSite)
20882101 ! This logic checks to make sure that the younger patch is not the youngest
20892102 ! patch. As mentioned earlier, we try not to fuse it.
20902103
2091- elseif ( .not. associated (currentPatch% younger,currentSite % youngest_patch ) ) then
2104+ elseif ( associated (currentPatch% younger) ) then
20922105
20932106 if (debug) &
20942107 write (fates_log(),* ) ' fusing to younger patch because oldest one is too small' , &
20952108 currentPatch% area
2096-
2109+
20972110 youngerPatch = > currentPatch% younger
20982111 call fuse_2_patches(currentSite, youngerPatch, currentPatch)
20992112
@@ -2102,22 +2115,44 @@ subroutine terminate_patches(currentSite)
21022115 endif
21032116 endif
21042117 endif
2105-
2106- currentPatch = > currentPatch% older
21072118
2119+ ! It is possible that an incredibly small patch just fused into another incredibly
2120+ ! small patch, resulting in an incredibly small patch. It is also possible that this
2121+ ! resulting incredibly small patch is the oldest patch. If this was true than
2122+ ! we would had been at the end of the loop, and left with an incredibly small patch.
2123+ ! Think this is impossible? No, this really happens, especially when we have fires.
2124+ ! So, we don't move forward until we have merged enough area into this thing.
2125+
2126+ if (currentPatch% area > min_patch_area_forced)then
2127+ currentPatch = > currentPatch% older
2128+ count_cycles = 0
2129+ else
2130+ count_cycles = count_cycles + 1
2131+ end if
2132+
2133+ if (count_cycles > max_cycles) then
2134+ write (fates_log(),* ) ' FATES is having difficulties fusing very small patches.'
2135+ write (fates_log(),* ) ' It is possible that a either a secondary or primary'
2136+ write (fates_log(),* ) ' patch has become the only patch of its kind, and it is'
2137+ write (fates_log(),* ) ' is very very small. You can test your luck by'
2138+ write (fates_log(),* ) ' disabling the endrun statement following this message.'
2139+ write (fates_log(),* ) ' FATES may or may not continue to operate within error'
2140+ write (fates_log(),* ) ' tolerances, but will generate another fail if it does not.'
2141+ call endrun(msg= errMsg(sourcefile, __LINE__))
2142+
2143+ ! Note to user. If you DO decide to remove the end-run above this line
2144+ ! Make sure that you keep the pointer below this line, or you will get
2145+ ! an infinite loop.
2146+ currentPatch = > currentPatch% older
2147+ count_cycles = 0
2148+ end if
2149+
21082150 enddo
21092151
21102152 ! check area is not exceeded
2111- areatot = 0._r8
2112- currentPatch = > currentSite% oldest_patch
2113- do while (associated (currentPatch))
2114- areatot = areatot + currentPatch% area
2115- currentPatch = > currentPatch% younger
2116- if ((areatot- area) > 0.0000001_r8 )then
2117- write (fates_log(),* ) ' ED: areatot too large. end terminate' , areatot
2118- endif
2119- enddo
2153+ call check_patch_area( currentSite )
21202154
2155+ return
21212156 end subroutine terminate_patches
21222157
21232158 ! =====================================================================================
0 commit comments