Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Droplet no quant #261

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
1bac116
Use full path for README image
azzaouit Oct 31, 2019
6b281b1
Merge branch 'master' into taha
azzaouit Oct 31, 2019
bce58aa
Update README.md
azzaouit Oct 31, 2019
fda72ef
Vortex Droplet 1-to-1
azzaouit Nov 11, 2019
b748b49
Update documentation
azzaouit Nov 11, 2019
c90baa6
Module type error
azzaouit Nov 11, 2019
a96a611
Don't generate plots
azzaouit Nov 12, 2019
bd9d4f7
Add mass balancing
azzaouit Nov 17, 2019
aa6eb62
Adaptive time stepping
azzaouit Nov 17, 2019
a96dd65
Fixed trajectory calculations
azzaouit Nov 17, 2019
d96612c
Flatten trajectory and add delta t
azzaouit Nov 17, 2019
372b797
mods
azzaouit Nov 17, 2019
9dd3bee
Parse trajectories on the fly
azzaouit Nov 21, 2019
b3feda4
Trajectory plotting
azzaouit Nov 21, 2019
dd27b1b
Checkpointing
azzaouit Nov 21, 2019
ff4e2a3
Bug fix
azzaouit Nov 21, 2019
19ab3b6
component-wise calculation
azzaouit Nov 22, 2019
f0870d9
Remove get time
azzaouit Dec 6, 2019
1ae1ef8
Send constant value
azzaouit Dec 17, 2019
4a9d520
Merge branch 'taha' into droplet-no-quant
azzaouit Dec 17, 2019
d526425
Removed unused imports
azzaouit Dec 27, 2019
8b20d47
Test without quantity and species
azzaouit Dec 27, 2019
3ebe02e
Force mpi
azzaouit Dec 27, 2019
dd601ee
Move params to main
azzaouit Dec 27, 2019
e7232b4
Pass num drops via command line
azzaouit Dec 27, 2019
ac7e287
Added script to run droplet in batches
azzaouit Dec 27, 2019
b279d14
Time droplet runs and output elapsed time
azzaouit Dec 27, 2019
2e82772
Record output runs
azzaouit Dec 30, 2019
4062892
plot num droplets vs running time
azzaouit Dec 30, 2019
9753967
Save droplet runs to csv
azzaouit Dec 30, 2019
80d23cd
Fixed import errror
azzaouit Dec 30, 2019
59de1ea
Add labels
azzaouit Dec 30, 2019
3a045be
Add real numbers for solving
azzaouit Jan 4, 2020
5caa2af
Save droplet trajectory (optional)
azzaouit Jan 4, 2020
2186d3d
Calculate speed and radial pos from velocity on the fly
azzaouit Jan 4, 2020
51165b1
Import numpy only if needed
azzaouit Jan 4, 2020
0ad1277
Calculate time indicies on the fly when plotting
azzaouit Jan 4, 2020
b0ab53d
fix missing speed
azzaouit Jan 4, 2020
b2969b1
Make save droplet history optional
azzaouit Jan 4, 2020
d30e3eb
Move params to the main function
azzaouit Jan 5, 2020
5227489
Removed unused import
azzaouit Jan 5, 2020
4e9ed01
Remove batch run droplet
azzaouit Jan 5, 2020
c8ff592
merge nbody changes
azzaouit Jan 5, 2020
1784c97
Throw an error if mpi4py is not found (remove silent fallback to mp)
azzaouit Jan 5, 2020
2cd54fd
Fix off by one error in module reload check
azzaouit Jan 5, 2020
7dc796c
Revert "Throw an error if mpi4py is not found (remove silent fallback…
azzaouit Jan 5, 2020
2dbc280
Revert "Revert "Throw an error if mpi4py is not found (remove silent …
azzaouit Jan 5, 2020
3cb61d3
module save in droplet constructor
azzaouit Jan 5, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ A Python library for network dynamics modeling and HPC simulation.
[![Build Status](https://travis-ci.org/dpploy/cortix.svg?branch=master)](https://travis-ci.org/dpploy/cortix)
[![PyPI version](https://badge.fury.io/py/cortix.svg)](https://badge.fury.io/py/cortix)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/Django.svg)](https://badge.fury.io/py/cortix)

[![codecov](https://codecov.io/gh/dpploy/cortix/branch/master/graph/badge.svg)](https://codecov.io/gh/dpploy/cortix)

![](cortix/docs/cortix-cover.png)

![](https://cortix.org/cortix-cover.png)

## What is Cortix?

Expand Down
88 changes: 24 additions & 64 deletions cortix/examples/droplet_swirl/droplet.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
import scipy.constants as const
from scipy.integrate import odeint
from cortix.src.module import Module
from cortix.support.phase import Phase
from cortix.support.specie import Specie
from cortix.support.quantity import Quantity

class Droplet(Module):
'''
Expand All @@ -24,7 +21,7 @@ class Droplet(Module):
`visualization` sends data to a visualization module.
'''

def __init__(self):
def __init__(self, save=True):
'''
Attributes
----------
Expand All @@ -34,6 +31,8 @@ def __init__(self):
show_time: tuple
Two-element tuple, `(bool,float)`, `True` will print to standard
output.
save: bool
Save droplet history across time
'''

super().__init__()
Expand All @@ -47,9 +46,11 @@ def __init__(self):

self.bounce = True
self.slip = True
self.save = save

species = list()
quantities = list()
if self.save:
self.positions = []
self.velocities = []

self.ode_params = dict()

Expand All @@ -59,42 +60,12 @@ def __init__(self):
self.ode_params['droplet-xsec-area'] = np.pi * (self.droplet_diameter/2.0)**2
self.ode_params['gravity'] = const.g

# Species in the liquid phase
water = Specie(name='water', formula_name='H2O(l)', phase='liquid', \
atoms=['2*H','O'])
water.massCC = 0.99965 # [g/cc]
water.massCCUnit = 'g/cc'
water.molarCCUnit = 'mole/cc'
species.append(water)

droplet_mass = 4/3 * np.pi * (self.droplet_diameter/2)**3 * water.massCC * \
water_massCC = 0.99965 # [g/cc]
droplet_mass = 4/3 * np.pi * (self.droplet_diameter/2)**3 * water_massCC * \
const.gram / const.centi**3 # [kg]
self.ode_params['droplet-mass'] = droplet_mass

# Spatial position
x_0 = np.zeros(3)
position = Quantity(name='position', formalName='Pos.', unit='m', value=x_0)
quantities.append(position)

# Velocity
v_0 = np.zeros(3)
velocity = Quantity(name='velocity', formalName='Veloc.', unit='m/s', value=v_0)
quantities.append(velocity)

# Speed
speed = Quantity(name='speed', formalName='Speed', unit='m/s', value=0.0)
quantities.append(speed)

# Radial position
radial_pos = Quantity(name='radial-position', formalName='Radius', unit='m', \
value=np.linalg.norm(x_0[0:2]))
quantities.append(radial_pos)

# Liquid phase
self.liquid_phase = Phase(self.initial_time, time_unit='s', species=species, \
quantities=quantities)
self.liquid_phase.SetValue('water', water.massCC, self.initial_time)

# Domain box dimensions: LxLxH m^3 box with given H.
# Origin of cartesian coordinate system at the bottom of the box.
# z coordinate pointing upwards. -L <= x <= L, -L <= y <= L,
Expand All @@ -104,11 +75,9 @@ def __init__(self):
# Random positioning of the droplet constrained to a box sub-region.
x_0 = (2 * np.random.random(3) - np.ones(3)) * self.box_half_length / 4.0
x_0[2] = self.box_height
self.liquid_phase.SetValue('position', x_0, self.initial_time)

# Droplet Initial velocity = 0 -> placed still in the flow
self.liquid_phase.SetValue('velocity', np.array([0.0,0.0,0.0]), \
self.initial_time)
self.initial_pos = self.position = x_0
self.velocity = np.zeros(3)

# Default value for the medium surrounding the droplet if data is not passed
# through a conneted port.
Expand All @@ -132,16 +101,11 @@ def run(self, *args):

# Interactions in the external-flow port
#---------------------------------------

position = self.liquid_phase.GetValue('position')
self.send( (time,position), 'external-flow' )

(check_time, velocity,fluid_props) = self.recv( 'external-flow' )
self.send((time, self.position), 'external-flow')
(check_time, velocity,fluid_props) = self.recv('external-flow')

assert abs(check_time-time) <= 1e-6
self.ode_params['flow-velocity'] = velocity
#medium_mass_density = fluid_props.mass_density # see Vortex
#medium_dyn_viscosity = fluid_props.dyn_viscosity # see Vortex
medium_mass_density = fluid_props[0]
medium_dyn_viscosity = fluid_props[1]

Expand All @@ -156,12 +120,12 @@ def run(self, *args):
# Interactions in the visualization port
#---------------------------------------

self.send( position, 'visualization' )
self.send(self.position, 'visualization' )

# Evolve droplet state to next time stamp
#----------------------------------------

time = self.__step( time )
time = self.__step(time)

self.send('DONE', 'visualization') # this should not be needed: TODO
return
Expand Down Expand Up @@ -229,10 +193,7 @@ def __step(self, time=0.0):
'''

if not self.bottom_impact:

x_0 = self.liquid_phase.GetValue('position', time)
v_0 = self.liquid_phase.GetValue('velocity', time)
u_vec_0 = np.concatenate((x_0,v_0))
u_vec_0 = np.concatenate((self.position,self.velocity))

t_interval_sec = np.linspace(0.0, self.time_step, num=2)

Expand All @@ -248,12 +209,8 @@ def __step(self, time=0.0):

u_vec = u_vec_hist[1,:] # solution vector at final time step

values = self.liquid_phase.GetRow(time) # values at previous time

time += self.time_step

self.liquid_phase.AddRow(time, values)

if not self.bottom_impact:

# Ground impact with bouncing drop
Expand All @@ -271,11 +228,14 @@ def __step(self, time=0.0):
u_vec[3:] = 0.0 # zero velocity
self.bottom_impact = True


# Save values (if necessary)
if self.save:
self.positions.append(self.position)
self.velocities.append(self.velocity)

# Update current values
self.liquid_phase.SetValue('position', u_vec[0:3], time)
self.liquid_phase.SetValue('velocity', u_vec[3:], time)
self.liquid_phase.SetValue('speed', np.linalg.norm(u_vec[3:]), time)
self.liquid_phase.SetValue('radial-position', np.linalg.norm(u_vec[0:2]),
time)
self.position = u_vec[0:3]
self.velocity = u_vec[3:]

return time
34 changes: 14 additions & 20 deletions cortix/examples/droplet_swirl/run_droplet_swirl.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
To run this case using MPI you should compute the number of
processes as follows:

`nprocs = n_droplets + 1 vortex + 1 cortix`
`nprocs = 2 * n_droplets + 1 cortix`

then issue the MPI run command as follows (replace `nprocs` with a number):

Expand All @@ -25,14 +25,13 @@

import scipy.constants as const


from cortix import Cortix
from cortix import Network
from cortix.examples.droplet_swirl.droplet import Droplet
from cortix.examples.droplet_swirl.vortex import Vortex


def main():
def main(n_droplets=5, end_time = 3 * const.minute, time_step = 0.2, create_plots=True):
'''Cortix run file for a `Droplet`-`Vortex` network.

Attributes
Expand All @@ -54,12 +53,6 @@ def main():
'''

# Configuration Parameters
n_droplets = 5
end_time = 3*const.minute
time_step = 0.2

create_plots = True

if n_droplets >= 2000:
create_plots = False

Expand All @@ -81,15 +74,13 @@ def main():
vortex.plot_velocity()

for i in range(n_droplets):

# Droplet modules (multiple).
droplet = Droplet()
droplet = Droplet(save=create_plots)
swirl.network.module(droplet)
droplet.end_time = end_time
droplet.time_step = time_step
droplet.bounce = False
droplet.slip = False
droplet.save = True

# Network port connectivity (connect modules through their ports)
swirl.network.connect( [droplet,'external-flow'],
Expand All @@ -111,10 +102,11 @@ def main():

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

positions = list()
for m in swirl.network.modules[1:]:
positions.append(m.liquid_phase.get_quantity_history('position')[0].value)
positions.append(m.positions)

fig = plt.figure(1)
ax = fig.add_subplot(111,projection='3d')
Expand All @@ -131,26 +123,26 @@ def main():

# All droplets' speed
fig = plt.figure(2)
plt.xlabel('Time [min]')
plt.xlabel('Time')
plt.ylabel('Speed [m/s]')
plt.title('All Droplets')

for m in modules[1:]:
speed = m.liquid_phase.get_quantity_history('speed')[0].value
plt.plot(list(speed.index/60), speed.tolist())
speeds = [np.linalg.norm(vel) for vel in m.velocities]
plt.plot(speeds)

plt.grid()
fig.savefig('speeds.png', dpi=300)

# All droplets' radial position
fig = plt.figure(3)
plt.xlabel('Time [min]')
plt.xlabel('Time')
plt.ylabel('Radial Position [m]')
plt.title('All Droplets')

for m in modules[1:]:
radial_pos = m.liquid_phase.get_quantity_history('radial-position')[0].value
plt.plot(list(radial_pos.index/60)[1:], radial_pos.tolist()[1:])
radial_pos = [np.linalg.norm(pos[0:2]) for pos in m.positions]
plt.plot(radial_pos[1:])

plt.grid()
fig.savefig('radialpos.png', dpi=300)
Expand All @@ -159,4 +151,6 @@ def main():
swirl.close()

if __name__ == '__main__':
main()
import sys
num_drops = int(sys.argv[1]) if len(sys.argv) > 1 else 5
main(n_droplets=num_drops, create_plots=True)
4 changes: 1 addition & 3 deletions cortix/src/cortix_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,13 @@ def __init__(self, use_mpi=False, splash=False, log_filename='cortix'):

self.__network = None
self.log_filename = log_filename

# Fall back to multiprocessing if mpi4py is not available
if self.use_mpi:
try:
from mpi4py import MPI
self.comm = MPI.COMM_WORLD
self.rank = self.comm.Get_rank()
self.size = self.comm.size
except ImportError:
self.use_mpi = False

# Setup the global logger
self.__create_logger()
Expand Down
4 changes: 2 additions & 2 deletions cortix/src/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Module:

'''

def __init__(self):
def __init__(self, save=True):
'''Module super class constructor.

Note
Expand Down Expand Up @@ -66,7 +66,7 @@ def __init__(self):
self.use_multiprocessing = True
self.ports = list()
self.log = logging.getLogger('cortix')
self.save = False
self.save = save

self.id = None

Expand Down