Full text
Department of Fish Biology, Fisheries and Aquaculture Flow-Organisms Simulation System FOrgSimS Version 0.2 Dr. Oleksandra Shumilova Berlin, September 2025 Copyright 2025 by IGB. All rights reserved. This document may not, in whole or in part, be copied, photocopied, reproduced, translated, or reduced to any electronic medium or machine readable format form without prior consent in written from IGB. Every effort has been made to ensure the accuracy of this manual. However, IGB makes no warranties with respect to this document and disclaims any implied warranties of merchantability and fitness for a particular purpose. IGB shall not be liable for any errors of incidental or consequential damages in connection with the performance or use of this document or the examples herein. The information in this document is subject to change without notice.
2 Contents Introduction 1. Overview 1.1. River hydrodynamics at confluences 1.2. River hydrodynamics with groynes 1.3. Fish motion and behavior at confluences 2. Design concepts 2.1. Analytical modeling of flow in straight river reaches 2.2. Analytical modeling of flow at river confluences 2.3. Analytical modeling of flow at a river reach with groynes 2.4. Particle tracking 2.5. Organisms motion 2.6. Organisms behavior 3. Examples of tests 3.1. Tracing of passive particles in a groyne field 4. Acknowledgements 5. References 6. Listing of the code
3 Introduction Understanding moveable organism movements and responses or interactions to their environment and habitat features is crucial for developing reliable predictive ecological models. Last three decades have seen extensive advances in agent-based modeling interactions of organisms with their environment (Grimm et al. 2024). These models employ a bottom-up approach in which relevant information about entities of a system at the lower level are compiled together with the theories about their behavior and then simulation with computer codes. Implementing those theories show emergence of properties at the system-level. However, the generalizations of modeling results have been often hampered by the lack of an explicit strategy for dealing with inherit complexities of modeled systems and uncertainties in modeling. A promising strategy called pattern-oriented modeling (POM) was introduced to make bottom-up modeling more rigorous (Grimm et al. 2005). This strategy provides a unifying framework for decoding the internal organization of agent-based complex systems and leads toward unified algorithmic theories of the relation between adaptive behavior and system complexity. Development of this Flow-Organisms Simulation (FOrgSimS) is primarily motivated by a necessity to better understand survival of fish at the meso-scale habitats of river reaches with engineering structures (e.g. groynes) and natural features (e.g. confluence) during a passage of toxic contaminants. Regulation of rivers has been conventionally accomplished with the construction of groynes – lateral dikes placed in sequences forming groyne fields along riverbanks and often close to confluences (Sukhodolov 2014). Groyne fields, a typical meso-habitat structure, provide spawning and nursing area for generalist fish species, whereas typically riverine gravel-spawning species are restricted to the heads of groynes as replacement spawning sites (Bischoff & Wolter 2001). Confluences and their mixing processes are important for several reasons. Tributaries, by delivering coarser alluvium, form substrate in fish habitats that are morphologically linked to shallow and deep areas with hydrodynamic structures containing counter currents, helical flow, streamwise-oriented vortical cells, and shear layers (Sukhodolov et al. 2023). Incomplete mixing close to tributaries and groyne fields can be an important factor that can reduce the rates of mortality in fish during hazardous situations as demonstrated by the recent fish kill in the Oder River (Köhler et al. 2024). The FOrgSimS is based on the key idea of POM, which uses multiple patterns observed in real systems to guide design of model structure (Grimm et al. 2005). Patterns used to design a model occur at different spatial and temporal scales and different hierarchical levels and the complex dynamic systems are understood through revealing how processes on different scales are interrelated. Modern agent-based modeling is guided by the standardized rules formulated in so called ODD (Overview, Design concepts, and Details) protocol (Grimm et al. 2006). This protocol includes detailed descriptions of: purpose, variables and scale, processes overview and scheduling, design concepts, initialization, input and description of sub-models. Such protocols help reusing the model code for expansion for more general modeling tasks. Although the first version of FOrgSimS is focused on the fish-flow interactions modeling in rivers, it is planned that the system will be expanded to model more general environments including airscapes, floodplains with riparian vegetation, insects and animals related by host-seeking behavior. Therefore, the ODD protocol provides the basis of the FOrgSimS. Present document provides detailed description of the modeling system including theoretical backgrounds, test data, validation and examples of modeling. The development and application of the system is a part of the research project titled “Confluence mixing: near-field hydrodynamic controls of the intermodal behavior and their implications for fish ecology (CofeMix+)” funded by the Deutsche Forschungsgemeinschaft (DFG).
4 1. Overview 1.1. River hydrodynamics at confluences River confluences are vital nodal points of fluvial networks and are hotspots of biodiversity in lotic freshwaters ecosystems. The flow structure at confluences is highly non-uniform and produces complex patterns within mixing interfaces that are visually apparent when incoming flows differ in colour or turbidity (Fig. 1). In some instances, mixing interfaces are narrow near the junction apex and gradually increase in width over distance (Fig. 1a,c). In other cases, the mixing interface originates downstream of a broad zone of stagnant water near the confluence apex and expands downstream rapidly (Fig. 1b,d). Such changes in the patterns indicate the intermodal behavior of mixing processes. The overall mixing rate, designating the interface pattern, has a considerable impact on the spread of potentially harmful pollutants. In 2022, during a drought along the Oder River, a lack of dilution compounded by increased water residence time enabled blooming of a brackish water algae producing a harmful toxin. Even though remote-sensing has demonstrated the potential danger of the algae bloom in the upstream reaches of the Oder, early measures failed to prevent the mass kill of fish. This failure can be partly explained by insufficient knowledge about the relations among remotely sensed patterns of mixing, actual mixing rates and their implications for fish ecology causing dramatic impairments. Theoretical generalizations and numerical modeling of confluence dynamics and mixing have been extensively developed during the last two decades. Advanced computational fluid dynamics (CFD) methods that directly resolve large-scale flow structures have been applied to river confluences (Constantinescu et al. 2011, Horna-Munoz et al. 2020). Fundamentally important was the development of a mode-switching hypothesis (Constantinescu et al. 2011). In this hypothesis, the mixing interface is in a shear-layer mode when the velocity difference between tributaries is large and can change to a wake mode when velocity difference is small when the merging flows have a similar velocity. Coupling of shallow flow theories of mixing layers and wakes with Rozowskii’s theory led to a new theoretical model of intermodal behavior of mixing interfaces (Sukhodolov et al. 2023). This analytical model explains both prolonged and fast mixing in concordant confluences, integrates the effects of lateral advective fluxes of momentum due to centrifugal forces and shows that their contribution to momentum exchange and mixing can be larger than the effects of bed friction alone (Sukhodolov et al. 2023). River confluences and their mixing processes are important for several reasons. Tributaries, by delivering coarser alluvium, form substrate in fish habitats that are morphologically linked to shallow and deep areas with hydrodynamic structures containing counter currents, helical flow and shear layers (Fig. 1). Flow discontinuities between these structures prevent mixing locally and cause substantial Fig. 1. Mixing patterns at the confluence of the rivers Oder and Warta near Küstrin. (a) At high flow 06/01/2000. (b) At low flow 09/03/2004. (c) Field-scale model of the river confluence at high flow conditions. (d) Field-scale model of the river confluence at high flow conditions.
5 differences in chemical composition, temperature and turbidity. At short distances (e.g. within confluence apex) fish benefit from the increase in downstream transport of prey in dendric networks (Grant et al. 2007). At long distances, the annual migration of salmonid fish to spawning grounds, the salmon run, is guided by incomplete mixing preserving the smell of unique dissolved minerals present at the spawning site (Scholz et al. 1976). Empirical research on fish ecology at river confluences has been mostly carried out with electrofishing and telemetry techniques and have repeatedly reported that river tributaries affect overall composition and spatial patterns of fish assemblages in the main river (Fernandes et al. 2004, Boddy et al. 2019). Although this research provides information on large spatial scales, knowledge about fish behavior at small scales relevant to the lateral scales of mixing interfaces mainly comes from laboratory studies. This research examines the effects of turbidity on the reactive distance in fishes – visual distance necessary to detect prey, which also depends on visual acuity related to a size of fish (Barrett et al. 1992, Zamor & Grossman 2007, Sliger & Grossman 2022). Another important variable controlling abundance patterns in micro-habitats is holding velocity (e.g. focal point) that ensures minimization of metabolic costs required to hold a position in a stream (Fausch 1984, Hill & Grossman 1993). These variables are tightly linked to the mechanisms of fish locomotion and interaction with turbulent structures (e.g. karman vortex gaiting) allowing fish to benefit energetically from wake structures (Liao et al. 2003; Liao 2022). Even though the laboratory research is schematized and involves serious methodological constrains such as fish days in captivity, they explain a common observation that, at river confluences, turbid water next to transparent water can act as an ideal refuge to escape predation while safely driftfeeding in the transparent water (Biswas & Boruah 2000). 1.2. River hydrodynamics with groynes Regulation of rivers has been conventionally accomplished with the construction of groynes – lateral dikes placed in sequences forming groyne fields along riverbanks and often close to confluences (Sukhodolov 2014). Flow separates on a groyne head and forms a secondary flow represented by a largescale vortex with a vertical axis of rotation called primary gyre. Deflection of the flow inside the groyne field by banks and upstream groyne leads to the development of a secondary gyre with an opposite direction of rotation to a primary gyre (Fig. 2). Location, mutual interactions, and energy exchange between gyres are the factors that create specific recirculating patterns. Groyne fields, a typical mesohabitat structure, provide spawning and nursing area for generalist fish species, whereas typically riverine gravel-spawning species are restricted to the heads of groynes as replacement spawning sites (Bischoff & Wolter 2001). Beside the limited size of the groyne heads, the main disadvantage for fish is the shear layer induced by the groyne head, which propagates towards the mid-channel and can transport emerging fry towards the main river flow where they might not survive. Fig. 2. Effects of groyne fields geometry on the patterns of mean flow velocity and mixing in groyne fields (from Sukhodolov 2014). (a) Distance between groynes is about the same as their length. (b) Distance is more than two times larger than the length of the groynes and two gyre systems is developing. (c) Visualization of the exchange between main river and the groyne field.
6 1.3. Fish motion and behavior at confluences Experimental observations and documentation of fish within confluences is very scarce and have been recently accomplished only in a laboratory conditions (Yuan et al. 2022). The study was performed in a 7 m long, 0.4 wide and 0.2 m deep flume. Test fish – carps with total number of 60 individuals of about 6 cm long were released after 1 min of accommodation in a cage. Then their trajectories and the flow hydrodynamics were measured using video cameras. The study reports that fish was moving around a boundary of separation zone and moving into either a tributary or into the main channel. Although the authors explain this observation as a choice of a fish dictated by the vorticity lines that guided their navigation, it seems like that fish was not adopted to their new environment and explored the way to escape by remaining in the corner of the flume where they are protected from two sides. The absence of reliable data for concluding on the behavior of fish at river confluences prompted our study using the RIVER-LAB research platform. In this study a 76 m long, 7 m wide and 40 cm deep model of a river confluence was created on the gravel-bed side arm of the Tagliamento River, Italy (Fig. 1c,d). These experiments allowed to document the motion of fish within the confluence mixing interface using video camera and scaling marking on the river bed (Fig. 3). The results show that fish is preferentially using a focal point at the interface between wake-like structure developing around the confluence apex and the jet-like flow approaching from the tributary. Fish was holding position in such focal points for prolonged periods of time ranging between 5 to 10 minutes and then moving to the slower water. After some period of rest fish were returning to the focal points. Such behavior is explained by advantages for feeding and minimizing energy for swimming. We suggest a hypothesis that this behavior can be also crucial for fish survival during the passage of toxins. The degree of intoxication most probably directly related to the time fish spends in non-toxic and toxic waters and the modeling with agent-based models can help to test this hypothesis. Fig. 3. Fish holding position at the focal points within the mixing interface in the RIVER-LAB experiments (August 2025). (a) The view of the mixing interface within the apex of a confluence model (the scaling mash is 10x10 cm). (b) Enlarged view (fish was about 3 cm long). (c) An example of fish trajectory observed in a wake flow. The purpose of the modeling with FOrgSimS in this study will be to apply agent-base pattern-oriented modeling to examine factors defining survival of fish in rivers polluted by toxic contaminants spreading through the river networks. Our model will simulate intoxication and mortality which is related to the time of fish residence and toxin concentration in flow areas through which the digital fish moves. If the accumulated toxins exceed certain thresholds, the fish will be designated as dead. In simulations we will explore the effects of different mixing scenarios at the confluence and we will look at which fish, depending on its initial position in the system and use of different habitats, have a better chance to survive. We will focus on relatively short time periods of few days that allows simplifications of fish energetics. The output of the simulations will allow qualitative comparison with the results of fish sampling that were completed immediately after the catastrophic mass kill on the Oder River in 2022. To validate the modeling of fish trajectories within confluence we will use the results of fish video recording coupled with data about flow structure. The results of simulations will be used as a primary tool to interpret the results of fish sampling surveys.
7 2. Design Concepts Numerical Hydrodynamic Models. Modeling of fish behavior using individual-based approach is a classical focus of many previous studies (Grimm & Railsback). An extensive review of the literature on this subject and specifically with respect to hydrodynamics modeling is recently presented by Goodwin et al. (2023). Advanced modeling of confluence have been carried out with eddy-resolving numerical models (Constantinescu et al. 2011), so called detached eddy simulations (DES), which provide insight into details of turbulent structure and to realistically reproduce such complex flows at the scales relevant (Fig. 4). However, the limitation of using such complex models for agent-based modeling is that they are extremally computational expensive and using their output within ABMs is problematic. Another class of numerical models, the so-called Reynolds Average Navier Stokes equations (RANS), is less computationally expensive than DES, but still requiring large number of vertices to construct computational domain and provides mainly information on mean flow velocities (Goodwin et al. 2023). Fig. 4. Examples of LES modeling of the turbulent flow structure at a river confluence. (a) Visualization of turbulent structures with particles (Kaskaskia-Copper Slough confluence from Rhoads & Sukhodolov 2004). (b) Spatial patterns of vertical vorticity in the instantaneous flow modeled with LES (from Constantinescu et al 2012). (c) Observed turbulent structures. Analytical Hydrodynamic Models. Grimm & Railsback (2005) highlighted the benefits for using analytical models together with ABMs: ”…The strength and weakness of agent-based models and analytical models are to a large degree inversely related. ABMs are designed for analyzing complex systems, but the more complex ABMs are, the harder they are to formulate, implement, analyze, understand, and communicate. Analytical models, on the other hand, have very limited ability to deal with complex systems of autonomous individuals. However, they are strong exactly in the ways that ABMs are inherently cumbersome”. The FOrgSimS is primarily based on analytical modeling of complex turbulent flows in rivers, which were advanced during the last three decades (Nikora 1992, Sukhodolov et al. 1998, Sukhodolov & Uijttewaal 2010, Sukhodolov et al. 2023). 2.1 Analytical modeling of flow in straight river reaches. Analytical modeling of river flows requires a generalized model for river channel geometry. Nikora (1992) suggested a parabolic cross-section profile (Fig. 5a) k hB = , (1) where and k are empirical parameters, B is the width of a channel, and h is the local depth. Eq. (1) can be rewritten as by = , where y is the riverbed elevation and b is the lateral coordinate with the origin at the point of symmetry of a channel cross-section (Fig. 5a). Parameters and evaluated from a river cross-sectional using the least squares method, and and k are then 1 =k , and (2) 1 1 2 + = . (3)
8 Fig. 5. (a) A scheme of a river cross-section Eq. (1). (b) Fitting measured river cross-section by the model (1)-(3). (c) Predicting spatially averaged shear stress patterns and depth on a river reach. The analytical model (1)-(3) provides the way for reconstructing 2-D and 3-D patterns of flow from the 1-D model of flow hydraulics gS h c u x u u t uf=+ + 2 2 , (4) 0= + + x Q t h B t B h , (5) where f c is hydraulic friction coefficient, g is gravity acceleration, h is mean river depth, u is mean flow velocity, Q is water discharge, S is water surface slope, t is time, u is mean velocity, and x is longitudinal coordinate. Eq. (4) - (5) describe dynamics and conservation of mass for the river flow. Quasi-uniform flow with zero substantial acceleration = + 0 x u u t u approximates equations (4)- (5) as (Sukhodolov et al. 2011) ghS u cf2 2 = , (6) ( ) 2 1 4 1 Q gBh M= , (7) uhBQ= , (8) where M is similarity parameter of quasi-uniform flow in an alluvial channel. Self-organization processes in fluvial system result in certain relationship between dimensions of the river channel and water discharge, which are described by Eq. (7). It was demonstrated that quasi-uniform flow depends on the characteristics of the riverbed material, and Nikora (1992) suggested a model for the similarity parameter M 50 1000 lg15.0 d h M= in gravel-bed rivers, (9) 12.09.0 =M in sand-bed rivers, (10) 0.2=M in rivers with cohesive riverbed, (11) where 50 d is median diameter of riverbed material. Eq. (1) together with (7) and (8) again gives a closed system for the variables ( ) Qu , ( ) QB , and ( ) Qh . Water discharge, riverbed material characteristic M and channel geometry described by and k represent a minimal set of parameters necessary to describe transport of momentum in a river channel. Analytical solution of this system provided by the following equations (Nikora 1992)
9 k k k k kQ M g u+ − + + + =4 2 4 1 3)1(4 1 , (12) k kQ g M h+ + =4 2 4 1 4 , (13) k k k k kQ g M B+ + =4 2 4 1 44 . (14) Hydraulic friction coefficient cf and bed shear stress related to friction velocity u* (cf=2(u*/u)2) can be defined as ( ) ( ) k k k k k fQ g M Sc + − + − + =4 12 4 1 1 234 0 2 , (15) where S0 is the slope of the river bed. Fig. 6 illustrates performance of the model (12)-(14). Fig. 6. Comparison between measured data (the Spree River at Frienbrinck, from Sukhodolov & Uijttewaal 2010) and model Eqs. (12)-(14) (solid lines are modeled and dashed lines are best fits). (a) Bulk flow velocity. (b) Bulk flow depth. (c) Width of the channel. Assuming that the riverbed slope and hydraulic resistance are constant, one obtains the lateral profile of depth averaged velocity (Nikora 1992) u(y) umax =[1-(2y B)k]2/3 , (16) where umax is the depth-averaged velocity at the centerline of the channel. The application of the model within the framework of the FOrgSimS is illustrated in Fig. 7. The input is represented by a hydrograph Q = f(t). For each value of discharge the bulk characteristic of flow are calculated using Eq. (12)-(15). Then 2-D patterns of flow velocity, depth, shear velocity and lateral fluxes of momentum are predicted using Eq. (16), Fig. 7. The bottom shear stresses are calculated as ( ) ( ) Sbyhgbyu // *= , (17) where S = S0 is the slope of the free surface of the flow.
16 Modeling hydrodynamics in a river reach with confluence. In tributaries and the main river, the river flow is modeled using approach described in the section 2.1. The area of junction, where the flows merge at circular trajectories (Fig. 9a), is modeled using Rozovskii (1957) theory in which the depth averaged mean vector of velocity is directed normal to the radii of the curvilinear junction part. The velocity profiles within the mixing interface then adjusted to fit Eq. (36) and (39) within the mixing interface, which is defined by conditions at the upstream boundary, by momentum ration at the junction, and by a zero velocity around junction apex. An example of a model of a river reach with confluence in the mixing layer mode and weak wake effect is shown in Fig. 14. Fig. 14. Example of turbulent flow field representation in a model of river reach with confluence (from Sukhodolov et al. 2023). (a) Magnitude and direction of mean flow velocity. (b) Patterns of turbulent shear stress. 2.3 Analytical modeling of flow at a river reach with groynes. Pioneering laboratory studies by Rehbock (1929) revealed development of circulation flow inside the groyne fields – the areas between two successive groynes. Later studies by Westrich (1978) introduced an aspect ratio ϰ, the ratio between length of groyne and the distance between successive groynes, as a quantitative criteria for circulation patterns in the groyne fields under emerged conditions. The critical value of ϰ = 0.5 delimits conditions for formation of either multiple (ϰ < 0.5) or single (ϰ > 0.5) circulation systems (Fig. 15). Fig. 15. Conceptual scheme of recirculation flow pattern in a groyne field as function of the aspect ratio between the length of the harbor side and the length of the shore side (from Sukhodolov et al. 2002). In groyne field with aspect ratio ϰ = 0.75 a large circulation system occupies almost entire groyne field area, Fig. 2a. Concomitantly with the increase of spacing between groynes and decrease of aspect ratio to ϰ = 0.35, the pattern of velocity vector in the groyne field exhibits two counter-rotating circulations, Fig. 2b. The larger circulation occupies more than 2/3 of entire groyne field area and is located in the downstream part of the groyne. Sukhodolov (2014) demonstrated that lateral profiles of mean flow velocity can be also fitted with the hyperbolic tangent function Eq. (34), Fig. 16. Assuming constant turbulent viscosity across the layer the lateral turbulent fluxes of momentum ''vu− are described by a reciprocal squared hyperbolic cosine function
17 Fig. 16. Comparison of predictions and measurements for the mean flow velocity in a groyne field (from Sukhodolov 2014). (a) Aspect ratio ϰ = 0.75 (symbols are measured data, solid lines Eq. (34)). (b) In the interface with intermediate behavior (solid line is Eq. (39)). 22 cosh 1'' uu vu t = − , ( ) 00 2 ,tanh 2 1yy u uu − == − . (40) Comparison of measured and predicted using Eq. (40) profiles of turbulent shear stress are shown in Fig. 17. Fig. 17. Comparison of predictions and measurements for the mean flow velocity in a groyne field (from Sukhodolov 2014). (a) Aspect ratio ϰ = 0.75 (symbols are measured data, solid lines Eq. (40)). (b) In the interface with intermediate behavior (solid line is Eq. (40)). Comparison of dimensionless local shear velocity values normalised with integral values of openchannel flow is shown in Fig. 18a. With emerged groynes, the bed shear stress (vertical turbulent flux of momentum) is greatly reduced inside the groyne field area, but inhomogeneous and slightly larger than in free channel when the groynes are submerged. The lateral shear stress (lateral turbulent flux of momentum) is greatly increased inside the mixing interface, Fig. 18b. It is clear in Fig. 18 that the increase in lateral turbulent fluxes of momentum can compensate for the lack of shear stress imposed by the groynes in the near bank area, but it is insufficient for considerable increase of flow resistance on the reach. Therefore, groynes affect flow resistance by constricting the active cross-sectional area of the river, which subsequently increases velocity and shear stress in the main flow. Fig. 18. Normalized lateral profiles of turbulence and their modeling and comparison with measured data (from Sukhodolov 2014). (a) Vertical fluxes of momentum. (b) Lateral fluxes of momentum.
18 2.4 Particle tracking. In the present version of the FOrgSimS a simple model of neutrally buoyant particle is implemented to model the advective and diffusive processes imposed on organisms by moving water. At this stage it does not account for individual vortices, which would be introduced in the next version of the software. The random walk model is a standard tool to mimic the behaviour of a tracer particle within a fluid, and can be described in its general form by a stochastic differential equation ( ) t td d,xu x= , ( ) ( ) ( ) ttt ,',, xuxuxu += , (41) where x is vector of coordinates, u is velocity vector, u is mean velocity vector, 'u is velocity fluctuation vector, and t is time. Equation (1) solved on a certain computation domain with initial conditions ( ) 0 0=tx , and the case-specific boundary conditions, provides a Lagrangian set of particles trajectories. These trajectories could be further processed to obtain characteristics of mixing that would otherwise be impossible to measure in field. Turbulence term is presented in the model by a normally distributed fluctuating increment defined on the grid by its values of standard deviation ( ) ( ) ( ) tRtt ,,3,' xxσxu = , (42) where σ is the vector of standard deviations for velocity components, and ( ) tR ,x is normally distributed with zero mean random value. Four-point inverse distance interpolation scheme are used to compute velocity vectors in the computational domain for both mean and turbulent velocities ( ) ( ) ( ) = = =4 1 4 1 /1 /, , mm mmm r rt t xu xu , (43) where r is distance between current position of a particle and the nearest nodes of the computational grid. In two-dimensional version of the model (41) currently used in the code, the horizontal components of the velocities are calculated using a simple numerical scheme ( ) ( ) ( ) ( ) ttuttutxttx ++=+ ' , (44) ( ) ( ) ( ) ( ) ttvttvtytty ++=+ ' , (45) where x is streamwise coordinate, y is transverse coordinate, t is time period, u and v are mean velocities in streamwise and transverse directions respectively, and 'u and 'v are the standard deviations of velocities along and normal to a local streamline of the flow. The time step was chosen as ( ) ( ) 2 ** 32/01.0 uhut += = 0.05 s, where is kinematic viscosity, * u is shear velocity, and h flow depth. The choice of the time step was tested by comparing measured trajectories of drifters and simulated trajectories, and was shown to ensure stability of numerical computations. The perfect reflection condition was set on the water’s edge of the groyne field. That means that if a particle reached that boundary it was reflected inside the groyne field area. The line connecting groyne tips of the groyne field was specified as the outer boundary of the groyne field. Initial conditions were specified by selecting the particles locations inside the groyne field area. 2.5 Organisms motion. In the present version of the FOrgSimS a simple model of passively moving neutrally buoyant particle is implemented to model simple organisms such as algae. At this stage it does not account for individual motions, which would be introduced in the next version of the software.
19 2.6 Organisms behavior. In the present version of the FOrgSimS a simple model of passively moving neutrally buoyant particle is implemented to model simple organisms such as algae. At this stage it does not account for individual motions and has no specified behavior, which would be introduced in the next version of the software. 3. Examples of tests 3.1 Tracing of passive particles in a groyne field Here, is the report on the first test of the code implementing the basic modules of the FOrgSimS (see listing of the code in the section 6): the grid processing module and neutral buoyance particle tracking module. The test case is a geometry and flow hydrodynamics measured in a groyne field on the Elbe River (Sukhodolov 2002). In the measurement study on the groyne field a set of tracer tracking was implemented using surface drifters, which position in the field tests was accurately mapped with a total station (Fig. 19). TopoFig. 19. Geometry of the test groyne field on the Elbe River and measured locations of the surface drifters (symbols with different colors represent individual drifters). The solid lines show trajectories of numerical particles in the verification tests. graphical and hydrodynamic measurements with acoustic Doppler Velocimeters allowed to create the computational mesh composed of 540 rectangular cells containing information about location, depth, magnitude and direction of time-averaged flow velocity and streamwise and lateral turbulence intensities. An example of the spatial pattern of streamwise turbulence intensity is shown in Fig. 20. Fig. 20. Spatial pattern of streamwise turbulent intensity of the flow in the test groyne field of the Elbe River. The darker contours represent stronger turbulence. The pattern also reflects the spatial arrangement of the flow into one-gyre recirculation system. In the numerical tests, the numerical tracers were released at the points corresponding to the locations of the physical surface drifters’ releases in the field tests (Fig. 19). An example of a screenshot of the FOrgSimS illustrates a typical trajectory of a numerical particle. It indicates that the particle experiences the effects of turbulence which move the particle out of stationary orbiting and the deviations from the smooth trajectory is sensitive to the intensity of turbulence. These tests are indicating that the code is realistically reproducing movement and turbulent diffusion.
20 Fig. 21. A screenshot of the FOrgSimS with an example of simulated trajectory of a particle released in the center of the recirculation gyre. The arrows show the magnitude and direction of the timemean flow velocity. Black solid line shows the water edge line. Green line is the trajectory of the particle. The trajectory indicates that in the area with stronger turbulence (see Fig. 20), the particle exhibited stronger deviation from the smooth line. 4. Acknowledgements I would like to thank Dr. Alexander Sukhodolov for the discussions and the help with developing the concept and structure of the simulating system, and for provision of the testing material. The system is developed with the support of the Deutsche Forschungsgemeinschaft (grant SU 405/11). 5. References Grimm V, Berger U, Meyer M, Lorscheid I. Theory for and from agent-based modeling: Insights from a virtual special issues and a vision. 2024. Environ. Mod. Soft. 178, 106088. Grimm V, Revilla E, Berger U, Jeltsch F, et al. Pattern-oriented modeling of agent-based complex systems: Lessons from ecology. 2005. Science 310, 987-991. Grimm V, Berger U, Bastiansen F, et al. A standard protocol for describing individual-based and agent-based models. 2006. Ecol. Model. 198, 115-126. Grimm V, Railsback SF. Individual-based Modeling and Ecology. 2005. Princeton Univ. Press. Goodwin RA, Lai YG, Taflin DE, Smith DL, McQuirk J, Trang R, Reeves R. Predicted near-term, out-of-sample fish passage, guidance, and movement across diverse river environments by cognitively relating momentary behavioral decisions to multiscale memories of past hydrodynamic experiences. 2023. Front. Ecol. Evol. 11, 703946. Sukhodolov A. Hydrodynamics of groyne fields in a straight river reach. 2014. J. Hydraul. Res. 52, 105-120. Bischoff A, Wolter C. The flood of the century on the river Oder: effects on the 0+ fish community and implications for floodplain restoration. 2001. Regul. Rivers: Res. Mgmt. 17, 171-190. Sukhodolov AN, Shumilova OO, Constantinescu GS, et al. Mixing dynamics at river confluences governed by intermodal behavior. 2023. Nature Geosci. 16, 89-93. Köhler J, Varga E, Spahr S, et al. Unpredicted ecosystem response to compound human impacts in a European river. 2024. Sci. Rep. 7, 16. Constantinescu GS, Miyawaki S, Rhoads BL, Sukhodolov AN, Kirkil G. Structure of turbulent flow at a river confluence with momentum and velocity ratios close to 1: Insight provided by eddy‐resolving numerical simulation. 2011. Water Resour. Res. 47, W05507.
21 Horna‐Munoz D, Constantinescu G, Rhoads, B, Lewis Q, Sukhodolov A. Density effects at a concordant bed natural river confluence. 2020. Water Resour. Res. 56, e2019WR026217. Sukhodolov AN, Shumilova OO, Constantinescu GS, Lewis QW, Rhoads BL. Mixing dynamics at river confluences governed by intermodal behavior. 2023. Nature Geosci. 16, 89-93. Grant EHC, Lowe WH, Fagan WF. Living in the branches: population dynamics and ecological processes in dendritic networks. 2007. Ecology Letters 10, 165-175. Scholz AT, Horrall RM, Cooper JC, Hasler AD. Imprinting to chemical cues: the basis for home stream selection in salmon. 1976. Science 192, 1247-1249. Fernandes C, Podos J, Lindberg JG. Amazonian ecology: Tributaries enhance the diversity of electric fishes. 2004. Science 305, 1960-1962. Boddy NC, Booker DJ, McIntosh AR. Confluence configuration of river networks controls spatial patterns in fish communities. 2019. Land. Ecol. 34, 187-201. Barrett JC, Grossman GD, Rosenfeld J. Turbidity-induced changes in reactive distance of rainbow trout. 1992. Trans. Am. Fish. Soc. 121, 437-443. Zamor RM & GD Grossman. Turbidity affects foraging success of drift-feeding rosyside dace. 2007. Trans. Am. Fish. Soc. 136, 167-176. Sliger R, Grossman GD. Foraging dynamics of a domesticated brook trout. 2022. N. Am. J. Fish. Man. 42, 13401348. Fausch, K.D. Profitable stream positions for salmonids: relating specific growth rate to net energy gain. 1984. Can. J. Zool. 62:441-451. Hill J, Grossman GD. An energetic model of microhabitat use for rainbow trout. 1993. Ecology 74, 685-698. Liao JC, Beal DN, Lauder GV, Triantafyllou MS. Fish exploiting vortices decrease muscle activity. 2003. Science 302, 1566-1569. Liao JC. Fish swimming efficiency. 2022. Current Biology 32, R589-R683. Biswas SP, Boruah S. Ecology of river dolphin in the Upper Brahmaputra. 2000. Hydrobiol. 430, 97-111. Sukhodolov A. Hydrodynamics of groyne fields in a straight river reach. 2014. Hydraul. Res. 52, 105-120. Yuan S, Xu L, Tang H, Xiao Y, Whittaker C. Swimming behavior of juvenile silver carp near the separation zone of a channel confluence. 2022. Int. J. Sediment Res. 37, 122-127. Rhoads BL, Sukhodolov AN. Spatial and temporal structure of shear layer turbulence at a river confluence. 2004. Water Resour. Res. 40, W06304. Constantinescu G, Miyawaki S, Rhoads BL, Sukhodolov A, Kirkil G. Structure of turbulent flow at a river confluence with momentum and velocity ratios close to 1: Insight provided by eddy-resolving numerical simulation. 2011. Water Resour. Res. 47, W05507. Nikora V. Channel Processes and Hydraulics of Small Rivers. 1992. Shtiinca: Kishinev. Sukhodolov A, Thiele M, Bungartz H. Turbulence structure in a river reach with sand bed. 1998. Water Resour. Res. 34, 1317-1334. Sukhodolov A, Uijttewaal WSJ. Assessment of a river reach for environmental fluid dynamic studies. 2010. J. Hydraul. Eng. 136, 880-888. Sukhodolov AN, Shumilova OO, Constantinescu GS, Lewis QW, Rhoads BL. Mixing dynamics at river confluences governed by intermodal behavior. 2023. Nat. Geosci. 16, 89-93. Cunge JA, Holly FM, Verwey A. Practical Aspects of Computational River Hydraulics. 1980. Pitman Advanced Publishing Program: London.
22 Sukhodolov AN, Nikora VI, Katolikov VM. Flow dynamics in alluvial channels: the legacy of Kiril V. Grishanin. 2011. J. Hydraul. Res. 49, 285-292. Sukhodolov AN, Sukhodolova TA. Case study: Effect of submerged aquatic plants on turbulent structure in a lowland river. 2010. J. Hydraul. Eng. 136, 434-446. Rozovskii IL. Flow of Water in Bends of Open Channels. 1957. Acad. Sci. Ukraine, Kiev. Sukhodolov AN, Uijttewaal WSJ, Engelhardt C. On the correspondence between morphological and hydrodynamical patterns of groyne fields. 2002. Earth Surf. Proces. Lanfroms 27, 289-305. Rehbock T. Das Flussbaulaboratorium der Technischen Hochschule in Karlsruhe. 1926. VDI-Verlag, Berlin, Germany. Westrich B. Massenaustausch in Strömungen mit Totwasserzonen unter stationären Fliessbedingungen. 1978. Tech. Report SFB 80/ET80, Institut für Hydromechanik, Universität Karlsruhe.
23 6. Listing of the code. /////////////////////////////////////////////////////////////////////////// // // PROJECT: Particle Tracking Model 0.1 // DESCRIPTION: Model Object // REFERENCE: PTModel.h // NOTES: Interface for the CNumGrid object // // Copyright (c) 2025 IGB, All rights reserved // Rev. 1.0 27.02.2025 // // Dr. O. Shumilova // /////////////////////////////////////////////////////////////////////////// #if !defined (AFX_PTMODEL_H__C3A4EB57_0C06_11D5_96EE_046809C1FFFF__INCLUDED_) #define AFX_PTMODEL_H__ C3A4EB57_0C06_11D5_96EE_04680SC1FFFF__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "NGrid.h" class CPTModel : public CObject { public: CPTModel (); virtual ~CPTModel (); CNumGrid m_grid; BOOL m_bGridLoaded; } ; #endif // !'defined (AFX_PTMODEL_H__C3A4EB57_0C06_11D5_96EE_046809C1FFFF__INCLUDED_) /////////////////////////////////////////////////////////////////////////// // // PROJECT: Particle Tracking Model 0.1 // DESCRIPTION: Model Object // REFERENCE: PTModel.cpp // NOTES: Implementation for the CNumGrid object // // Copyright (c) 2025 IGB, All rights reserved // Rev. 1.0 27.02.2025 // // Dr. O. Shumilova // /////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "FlowTrack.h" #include "PTModel.h"
24 #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif /////////////////////////////////////////////////////////////////////////// //Construction/Destruction /////////////////////////////////////////////////////////////////////////// CPTModel::CPTModel () { m_bGridLoaded = FALSE; } CPTModel::~CPTModel () { } /////////////////////////////////////////////////////////////////////////// // // PROJECT: Particle Tracking Model 0.1 // DESCRIPTION: Particle Object // REFERENCE: Particle.cpp // NOTES: Implementation for the CParticle object // // Copyright (c) 2025 IGB, All rights reserved // Rev. 1.0 16.03.2025 // // Dr. O. Shumilova // /////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "FlowTrack.h" #include "Particle.h" #include "math.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE(]=__ FILE_ ; #define new DEBUG_NEW #endif /////////////////////////////////////////////////////////////////////////// //Construction/Destruction /////////////////////////////////////////////////////////////////////////// CParticle::CParticle() { m_pGrid = NULL; m_pView = NULL; m_dt = 0.05; m_logPen.lopnColor = RGB(255, 0, 0); // red color for particle
25 m_logPen.lopnStyle = PS_SOLID; m_logPen.lopnWidth.x = m_logPen.lopnWidth.y = 1; m_nearestNodes.SetSize(4); m_bFirstTime = TRUE; } CParticle::~CParticle() { } void CParticle::SetCoordinatesXY(double dX, double dY) { m_dX = dx; m_dy = dy; } void CParticle::DrawParticle(CDC* pDC) { ASSERT (m_pGrid != NULL); CPoint point = m_pGrid->GetPoint (m_dX, m_dy); pDC->MoveTo (point.x - 2, point.y); pDC->LineTo (point.x + 3, point.y); pDC->MoveTo (point.x, point.y-2); pDC->LineTo (point.x, point.y+3); // TRACING: /* CNode node; node = (CNode) m_nearestNodes.GetAt (0); point = m_pGrid->GetPoint (node.m_dX, node.m_dY); pDC->MoveTo (point); for (int i=1; i < m_nearestNodes.GetSize(); i++) { node = (CNode) m_nearestNodes.GetAt (i); point = m_pGrid->GetPoint (node.m_dX, node.m_dY); pDC->LineTo (point); pDC->MoveTo (point); } node = (CNode) m_nearestNodes.GetAt (0); point = m_pGrid->GetPoint (node.m_dX, node.m_dY); pDC->LineTo (point); */ } // // General scheme: // ^ Ymax // LTN #2 RTN #1 | +Vy // + ----------- + | ^ // | | | | // | | | | // | | | +Vx <-------+-------> -Vx // | *x,y | | | // | | | | // | | | | // | | | -Vy // + ----------- + | // LBN #3 RBN #0 | // |
32 } return (dSumVR / dSumR) } double CParticle::Get_interpolated_Vy(double dXc, double dYc) { CNode node; double dR, dV, dX, dY; double dSumVR = 0.0; double dSumR = 0.0; double dN = 1.0; for (int i=0; i < m_nearestNodes.GetSize(); i++) { node = (CNode) m_nearestNodes.GetAt (i); dX = dXc - node.m_dX; dY = dYc - node.m_dY; dR = sqrt(dX * dX + dY * dY); dV = Get_Vy(&node); dR = pow(dR, -dN); dSumVR += (dV * dR); dsumR += dR; } return (dSumVR / dSumR); } double CParticle::Get_interpolated_V() { double dVx = Get_interpolated_Vx(m_dX, m_dY); double dVy = Get_interpolated_Vy(m_dX, m_dY); return (sqrt(dVx * dVx + dVy * dVy)); } // // Particle advection with mean velocity field is computed // using a forth-order Runge-Kutta scheme: // // k1 = dt * Vi(t, Xin) // k2 = dt * Vi(t+dt/2, Xin+k1/2) // k3 = dt * Vi(t+dt/2, Xin+k2/2) // K4 = dt * Vi(t+dt, Xin+k3) // Xin+l = Xin + k1/6 + k2/3 + k3/3 + k4/6 // // i = x, y Xi = X,Y // BOOL CParticle::Advect_Particle() { // 1 - compute increments in x and y directions: double dK1X = m_dt*Get_interpolated_Vx(m_dX, m_dY); double dK1Y = m_dt*Get_interpolated_Vy (m_dX, m_dY); double dK2X = m_dt*Get_interpolated_Vx (m_dX+dK1X/2, m_dy+dK1Y/2); double dK2Y = m_dt*Get_interpolated_Vy (m_dX+dK1X/2, m_dY+dK1Y/2); double dK3X = m_dt*Get_interpolated_Vx(m_dX+dK2X/2, m_dY+dK2Y/2); double dK3Y = m_dt*Get_interpolated_Vy (m_dX+dK2X/2, m_dv+dK2Y/2);
33 double dK4X = m_dt*Get_interpolated_Vx (m_dx+dK3X, m_dY+dK3Y); double dK4Y = m_dt*Get_interpolated_Vy (m_dX+dK3X, m_dYy+dK3Y); double dX = dK1X/6.0 + dK2X/3.0 + dK3X/3.0 + dK4X/6.0; double dY = dK1Y/6.0 + dK2Y/3.0 + dK3Y/3.0 + dK4Y/6.0; // 2 - move particle: m_dX += dX; m_dY += dY; // 3 - calculate dispersion: m_dX += Get_dX_turbulent(); m_dY += Get_dX_turbulent(); // 4 - check if particle still in current cell: if (IsParticleInCell()) return TRUE; //5 – // DefineIntersect (m_dX - dX, m_dY - dY, m_dX, m_dY); return FALSE; } BOOL CParticle::IsParticleBeneath(double dY) { CNode* pLNode = (CNode*) &m_nearestNodes.GetAt(3); CNode* pRNode = (CNode*) &m_nearestNodes.GetAt (0); double dYl = pLNode->m_dY; double dY2 = pRNode->m_dY; if (dY < dYl && dY < dY2) return TRUE; if (dY > dYl && dY < dY2) return TRUE; if (dY < dYl && dY > dY2) return TRUE; return FALSE; } BOOL CParticle::IsParticleOnTop(double dY) { CNode* pLNode = (CNode*) &m nearestNodes.GetAt(2); CNode* pRNode = (CNode*) &m_nearestNodes.GetAt(1); double dY1 = pLNode->m_dY; double dY2 = pRNode->m_dY; if (dY > dYl && dY > dY2) return TRUE; if (dY < dYl && dY > dY2) return TRUE; if (dY > dY1 && dY < dY2) return TRUE; return FALSE; } BOOL CParticle::IsPartic1eOnLeft(double dX) { CNode* pTNode = (CNode*) &m_nearestNodes.GetAt(2); CNode* pBNode = (CNode*) &m_nearestNodes.GetAt(3); double dX1 = pTNode->m_dX;
34 double dX2 = pBNode->m_dX; if (dX > dX1 && dX > dX2) return TRUE; if (dX < dX1 && dX > dX2) return TRUE; if (dX > dX1 && dX < dX2) return TRUE; return FALSE; } BOOL CParticle::IsPartic1eOnRight(double dX) { CNode* pTNode = (CNode*) &m_nearestNodes.GetAt(1); CNode* pBNode = (CNode*) &m_nearestNodes.GetAt(0); double dX1 = pTNode->m_dX; double dX2 = pBNode—>m_dx; if (dX < dX1 && dX < dX2) return TRUE; if (dX > dX1 && dX < dX2) return TRUE; if (dX < dX1 && dX > dX2) return TRUE; return FALSE; } void CParticle::DefineIntersect(double dXo, double dYo, double dX, double dY) { CNode* pNode _ 1; CNode* pNode _ 2; if (IsParticleBeneath(dY)) { pNode_1 = (CNode*) &m_nearestNodes.GetAt(3); pNode_2 = (CNode*) &m_nearestNodes.GetAt(0); TRACE("Particle at bottom\n"); } if (IsPartic1eOnTop(dY)) { pNode_1 = (CNode*) &m_nearestNodes.GetAt(2); pNode_2 = (CNode*) &m_nearestNodes.GetAt(1); } if (IsPartic1eOnLeft(dX)) { pNode_1 = (CNode*) &m_nearestNodes.GetAt(2); pNode_2 = (CNode*) &m_nearestNodes.GetAt(3); } if (IsParticleOnRight(dX)) { pNode_1 = (CNode*) &m nearestNodes.GetAt(0); pNode_2 = (CNode*) &m_nearestNodes.GetAt(1); } double dX1 = pNode_1->m_dX; double dY1 = pNode_1->m_dY; doub1e dX2 = pNode_2 —>m_dX; doubl dY2 = pNode_1—>m_dY; double dA1 =(dY2 - dYl) / (dX2 - dXl); double dBl dY1 – dA1 * dX1; double dA2 = (dY - dYo) / (dX - dXo); double dB2 = dY - dA2 * dX;
35 double f_dX = (dB2 - dB1) / (dA2 - dA1); double f_dY = dA1 * m_dX + dB1; } void CParticle::WalkingParticle(CDC *pDC) { int k = 0; CWaitCursor wait; m_logPen.1opnColor = RGB(0, 255, 0); CPen pen; CPen* pOldPen; CPoint point; if (!pen.CreatePenIndirect(&m_1ogPen)) return; pOldPen = pDC->Se1ectObject(&pen); srand((unsigned)time( NULL )); for (int i=0; i < 1000; i++) { DrawParticle(pDC); if (!Advect_Particle()) { GetNodes(); } } pDC->SelectObject(pOldPen); } double CParticle::GetRandom(double dMean, double dVar) { double dVal; double dsum: dSum = 0.0; for (int i=0; i < 50; i++) { dVa1 = (double) (rand() / (double) RAND_MAX); dSum += dVa1; } dVal =(dSum - 25.0) / sqrt(50.0/12.0); dVal = dMean + dVal*dVar; return dVal; } double CPartic1e::Get_dX_turbu1ent() { return (m_dt * GetRandom(0.0, 0.3)); }
36 /////////////////////////////////////////////////////////////////////////// // // PROJECT: Particle Tracking Model 0.1 // DESCRIPTION: Particle Object // REFERENCE: Particle.h // NOTES: Interface for the GParticle object // // Copyright (c) 2025 IGB, All rights reserved // Rev. 1.0 16.03.2025 // // Dr. O. Shumilova // /////////////////////////////////////////////////////////////////////////// #if defined(AFX_PARTICLE_H_BDE556E0_1174_11D5_96EE_046809C10000_INCLUDED) #define AFX_PARTICLE_H_BDE556E0_1174_11D5_96EE_046809Cl0000_INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "NGrid.h" typedef CTypedPtrArray<CPtrArray, CNode*> CNPtrArray; class CParticle : public CObject { public: double Get_dX_turbulent(); double GetRandom(double dMean, double dVar); void DefineIntersect(double dXo, double dYo, double dX, double dY); BOOL IsParticleOnRight(double dX); BOOL IsParticleOnLeft(double dX); BOOL IsParticleOnTop(double dY); BOOL IsParticleBeneath(double dY); void WalkingParticle(CDC* pDC); void GetNodes(); CParticle(); virtual ~CParticle(); void SetCoordinatesXY(double dX, double dY); void DrawParticle(CDC* pDC); BOOL GetBottomRightNode(); // LTN +------+ RTN BOOL GetTopRightNode(); // | | BOOL GetBottomLeftNode(); // | * | BOOL GetTopLeftNode(); // LBN +------+ RBN ///////////////////////////////////////////////////////////////////// // BOOL IsParticleinCell(); // BOOL IsLeftBoundary(); // location BOOL IsRightBoundary(); // descriptive BOOL IsTopBoundary(); // functions BOOL IsBotBoundary(); //
37 ///////////////////////////////////////////////////////////////////// / double Get_interpolated_V(); double Get_Vx(CNode* pNode); double Get_Vy(CNode* pNode); double Get_interpolated_Vy(double dXc, double dYc); double Get_interpolated_Vx(double dXc, double dYc); ///////////////////////////////////////////////////////////////////// / BOOL Advect_Particle(); double m_dX; // current coordinate in X direction double m_dY; // current coordinate in Y direction double m_dZ; // current coordinate in Z direction // (Z origin is set at the free surface) double m_dt; // time increment CNumGrid* m_pGrid; // pointer to a grid CView* m_pView; // LOGPEN m_logPen; nodesArray m_nearestNodes; BOOL m_bFirstTirne; } ; #endif //defined(AFX_PARTICLE_H_BDE556E0_1174_11D5_96EE_046809Cl0000_INCLUDED_) /////////////////////////////////////////////////////////////////////////// // // PROJECT: Particle Tracking Model 0.1 // DESCRIPTION: Grid Object // REFERENCE: NGrid.cpp // NOTES: Implementation for the CNumGrid object // // Copyright (c) 2025 IGB, All rights reserved // Rev. 1.0 05.03.2025 // // Dr. O. Shumilova // /////////////////////////////////////////////////////////////////////////// #include “stdafx.h” #include “math.h” #include “FlowTrack.h” #include “NGrid.h” #ifdef DEBUG #undef THIS_FILE static char THIS_FILE[]= __FILE__; #define new DEBUG_NEW #endif /////////////////////////////////////////////////////////////////////////// //Construction/Destruction /////////////////////////////////////////////////////////////////////////// CNode::CNode()
38 { m_dX = 0.0f; m_dY = 0.0f; m_dH = 0.0f; m_dV = 0.0f; m_dD = 0.0f; } CNode::~CNode() { } CWEPoint::CWEPoint() { m_dX = 0.0f; m_dY = 0.0f; m_dD = 0.0f; } CWEPoint::-CWEPoint() { } CNumGrid::CNumGrid() : m_rectView(0, 0, 0, 0) { m_dXmin = 0.0f; m_dYmin = 0.0f; m_dXmax = 17.0f; m_dYmax = 9.0f; m_dVmin = 0.0f; m_dVmax = 0.0f; m_dAspectX = 1.0f; m_dAspectY = 1.0f; m_dAspectV = 40; // 0.5 m/s is 40 picsels } CNumGrid::~CNumGrid() { } /////////////////////////////////////////////////////////////////////////// // // Data input from an external ASCII data file. File structure: // x, y, h, V, dir (coordinates, depth, speed and direction of // the flow). Every string pertains to a specific node of the // grid. // Notes: no checking for correct file structure // 28.02.01 BOOL CNumGrid::Load_from_File(CString strPathName) { FILE* m_pFile; CString strError; if ((m_pFile = fopen(strPathName, "rb")) == NULL)
39 { strError.Format ("Cannot find data file: %s", strPathName); AfxMessageBox (strError, MB_ICONEXCLAMATION); return FALSE; } else { float x, y, h, V, dir; while (!feof (m_pFile)) { fscanf (m_pFile, "%f %f %f %f %f\n", &x, &y, &h, &V, &dir); CNode node; node.SetCoordinates ((double) x, (double) y); node.SetVelocity ((double) V, (double) dir); node.SetDepth ((double) h); m_nodes.Add (node); } fclose (m_pFile); } return TRUE; } /////////////////////////////////////////////////////////////////////////// // // MeasureGrid function provides the estimates of main sizes // for grid (max and min coordinates, velocity scale...) // void CNumGrid::MeasureGrid() { for (int i = 0; i < m_nodes.GetSize(); i++) { CNode node; node = m_nodes.GetAt (i); if (node.m_dX < m_dXmin) m_dXmin = node.m_dX; if (node.m_dX > m_dXmax) m_dXmax = node.m_dX; if (node.m_dY < m_dYmin) m_dYmin = node.m_dY; if (node.m_dY > m_dYmax) m_dYmax = node.m_dY; if (node.m_dV < m_dVmin) m_dVmin = node.m_dv; if (node.m_dV > m_dVmax) m_dVmax = node.m_dV; } } void CNumGrid::ComputeAspects () { if (m_rectView.Width()> 0) m_dAspectX = fabs(m_dXmax - m_dXmin) / m_rectView.Width(); if (m_rectView.Height()> 0) m_dAspectY = fabs(m_dYmax - m_dYmin) / m_rectView.Height(); } CPoint CNumGrid::GetPoint (double dX, double dY) { CPoint pntReturn; int nX = m_rectView.right - (int) ((dX - m_dXmin) / m_dAspectX); int nY = m_rectView.bottom - (int) ((dY - m_dYmin) / m_dAspectY); pntReturn.x = nX; pntReturn.y = nY;
40 return pntReturn; } double CNumGrid::Get_X_fromPoint (CPoint point) { double dRet = m_dXmin+(m_rectView.right - point.x)*m_dAspectX; return dRet; } double CNumGrid::Get_Y_fromPoint (CPoint point) { double dRet = m_dYmin+ (m_rectView.bottom-point.y) *m_dAspectY; return dRet; } void CNumGrid::DrawNodes (CDC* pDC) { for (int i=0; i < m_nodes.GetSize(); i++) { CNode node; node = m_nodes.GetAt (i); CPoint point; point = GetPoint (node.m_dX, node.m_dY); pDC->Ellipse(point.x-2, point.y-2, point.x+2, point.y+2); } } void CNumGrid::DrawWaterEdge (CDC*pDC) { CPoint pntFrom; CPoint pntTo; CNode node; for (int i=0; i < m_nodes.GetSize(); i++) { node = m_nodes.GetAt (i); if (node.m_dH == 0.0) { pntFrom = GetPoint (node.m_dX, node.m_dY); break; } } for (i=0; i < m_nodes.GetSize(); i++) { node = m_nodes.GetAt (i); if (node.m_dH == 0.0) { pntTo = GetPoint (node.m_dX, node.m_dY); pDC->MoveTo (pntFrom); pDC->LineTo (pntTo); pntFrom = pntTo; } } }
41 CPoint CNumGrid::GetVecorHeadPoint (CNodenode) { CPoint pntReturn; CPoint pntNode; double dalfa; double dBeta = node.m_dD; double dU; double dV; double dPi = 3.1415926535; if (dBeta >= 0.0 || dBeta < 90.0) { dalfa = dPi * (90.0 - dBeta) / 180.0; dU = node.m_dV * cos(dAlfa); dV = node.m_dv * sin(dAlfa); } if (dBeta >= 90.0 || dBeta < 180.0) { dAlfa = dPi * (dBeta - 90.0) / 180.0; dU = node.m_dv * cos(dAlfa); dV = node.m_dv * sin(dAlfa); } if (dBeta >= 180.0 || dBeta < 270.0) { dAlfa = dPi * (270.0 - dBeta) / 180.0; dU = -node.m_dV * cos(dAlfa); dV = -node.m_dV * sin(dAlfa); } if (dBeta >= 270.0 || dBeta < 360.0) { dAlfa = dPi * (dBeta - 270.0) / 180.0; dU = -node.m_dV * cos(dAlfa); dV = node.m_dV * sin(dAlfa); } pntNode = GetPoint (node.m_dX, node.m_dY); pntReturn.x = pntNode.x + (int) (dU * m_dAspectV); pntReturn.y = pntNode.y - (int) (dV * m_dAspectV); return pntReturn; } void CNumGrid::DrawArrows (CDC* pDC, CPoint pntCentre, CPoint pntHead) { int nU = pntHead.x - pntCentre.x; // streamwise component int nV = pntHead.y - pntCentre.y; // transverse component if (nU == 0.0 & nV == 0.0) return; double dL = 0.3 * sqrt(nU*nU + nV*nV); int nX = (int) (dL*cos(atan2( abs(nV), abs(nU) ) + 20.0*3.1415/180.0)); int ny = (int) (dL*sin(atan2( abs(nV), abs(nU) ) + 20.0*3.1415/180.0)); int iX = (int) (dL*cos(atan2( abs(nV), abs(nU) ) - 20.0*3.1415/180.0));