Version: Pizza3 v.1.006
Maintained by: INRAE\olivier.vitrac@agroparistech.fr
Welcome to Usage Class Examples
Select a module in the left menu to view usage examples. These examples are not for production and are automatically extracted from the main section of each module.
Back to the Python'Pizza3 documentation.
When no module is selected, you see this welcome page. They are used to test classes with typical codes. The main section often serves as a testing script, example usage block, or self-contained test block. It's a way to demonstrate how the module's functionality works or to run simple unit tests and examples inline.
Generated on: 2025-02-20 21:47:30
b = bdump("dump.one") b.map(1, "id", 3, "x", 4, "y", 5, "z") while True: time = b.next() if time == -1: break print(f"Snapshot Time: {time}") _, _, _, bonds, _, _ = b.viz(time, 1) print(f"Bonds: {bonds}")
l = ldump("dump.one") l.map(1, "id", 3, "x", 4, "y", 5, "z", 6, "end1x", 7, "end1y", 8, "end2x", 9, "end2y") while True: time = l.next() if time == -1: break print(f"Snapshot Time: {time}") _, box, _, _, _, lines = l.viz(time, 1) print(f"Lines: {lines}")
m = mdump("mesh.one") m.map(2, "temperature") m.tselect.all() while True: time = m.next() if time == -1: break print(f"Snapshot Time: {time}") _, box, nodes, elements, nvalues, evalues = m.viz(time, 1) print(f"Nodes: {nodes}") print(f"Elements: {elements}")
t = tdump("dump.one") t.map(1, "id", 3, "x", 4, "y", 5, "z", 6, "corner1x", 7, "corner1y", 8, "corner1z", 9, "corner2x", 10, "corner2y", 11, "corner2z", 12, "corner3x", 13, "corner3y", 14, "corner3z") while True: time = t.next() if time == -1: break print(f"Snapshot Time: {time}") _, box, atoms, bonds, tris, lines = t.viz(time, 1) print(f"Triangles: {tris}")
datafile = "../data/play_data/data.play.lmp" X = data(datafile) Y = dump("../data/play_data/dump.play.restartme") t = Y.time() step = 2000 R = data(Y,step) R.write("../tmp/data.myfirstrestart.lmp")
import sys
Example usage
try: datafile = "../data/play_data/data.play.lmp" X = data(datafile) Y = dump("../data/play_data/dump.play.restartme") step = 2000 R = data(Y, step) R.write("../tmp/data.myfirstrestart.lmp") except Exception as e: logger.error(f"An error occurred during execution: {e}") sys.exit(1)
List available forcefields
dforcefield.list_forcefield_subclasses(printflag=True,additional_modules=None) # we could add other modules
We reuse a high-level forcefield
mywater = dforcefield( base_class="water", userid = "my customized water", rho = 900, q1 = 0.1 )
Test dynamic water class using ulsph as the base class
dynamic_water = dforcefield( base_class='ulsph', beadtype=1, userid="dynamic_water", USER=parameterforcefield( rho=1000, c0=10.0, q1=1.0, Cp=1.0, taitexponent=7, contact_scale=1.5, contact_stiffness="2.5*${c0}^2*${rho}" ) ) print(f"Water parameters: {dynamic_water.parameters}") print(f"Water name: {dynamic_water.name}") print(f"Water Cp: {dynamic_water.Cp}") dynamic_water
Test dynamic solidfood class using tlsph as the base class
dynamic_solidfood = dforcefield( base_class='tlsph', beadtype=2, userid="dynamic_solidfood",
USER=parameterforcefield( #<--- note that USER is not used in this case
rho=1000, c0=10.0, E="5*${c0}^2*${rho}", nu=0.3, q1=1.0, q2=0.0, Hg=10.0, Cp=1.0, sigma_yield="0.1*${E}", hardening=0, contact_scale=1.5, contact_stiffness="2.5*${c0}^2*${rho}"
)
) print(f"Solidfood parameters: {dynamic_solidfood.parameters}") print(f"Solidfood name: {dynamic_solidfood.name}") repr(dynamic_solidfood)
Test dynamic saltTLSPH class using tlsph as the base class
dynamic_salt = dforcefield( base_class='tlsph', beadtype=3, userid="dynamic_salt", USER=parameterforcefield( rho=1000, c0=10.0, E="5*${c0}^2*${rho}", nu=0.3, q1=1.0, q2=0.0, Hg=10.0, Cp=1.0, sigma_yield="0.1*${E}", hardening=0, contact_scale=1.5, contact_stiffness="2.5*${c0}^2*${rho}" ) ) print(f"Salt TLSPH parameters: {dynamic_salt.parameters}") print(f"Salt TLSPH name: {dynamic_salt.name}") repr(dynamic_salt)
Test dynamic rigidwall class using none as the base class
dynamic_rigidwall = dforcefield( base_class='none', # Assuming a class `none` exists beadtype=4, userid="dynamic_rigidwall", USER=parameterforcefield( rho=3000, c0=10.0, contact_scale=1.5, contact_stiffness="2.5*${c0}^2*${rho}" ) ) print(f"Rigidwall parameters: {dynamic_rigidwall.parameters}") print(f"Rigidwall name: {dynamic_rigidwall.name}") repr(dynamic_rigidwall)
create a new food and save it on disk
newfood = dynamic_solidfood.copy(rho=2100,q1=4,E=1000,name="new food") repr(newfood) newfood.base_repr() fname = newfood.save(overwrite=True)
load again the same file
newfood2 = dforcefield.load(fname)
compare the content
newfood.compare(newfood2,printflag=True)
note that the variables are automatically identified and added to parameters if missing
newfood.parameters = parameterforcefield(a=1,b=2) missingvars = newfood.missingVariables() print('updated newfood:\n') repr(newfood) print('missing variables in updated newfood:\n') repr(missingvars)
compare the content
newfood.compare(newfood2,printflag=True)
check the parser
content = """
DFORCEFIELD SAVE FILE
base_class="tlsph" beadtype = 1 userid = "dynamic_water" version = 1.0 description:{forcefield="LAMMPS:SMD", style="tlsph", material="water"} name:{forcefield="LAMMPS:SMD", material="water"} rho = 1000 E = "5*${c0}^2*${rho}" nu = 0.3
Usage example
-------------
Initialize a dscript object
S = dscript()
Add script lines/items with placeholders for variables
S[3] = "instruction .... with substitution rules ${v1}+${var2}" S['alpha'] = "another script template ${v3}"
Set a custom attribute for a specific line
S[3].attribute1 = True
Reorder script lines/items
T = S[[1,0]]
Define global variables in DEFINITIONS
S.DEFINITIONS.a = 1 S.DEFINITIONS.b = 2
Update a script line and enable evaluation of its content
S[0] = "$a+$b" S[0].eval = True
Set a line as mandatory (not facultative)
S[3].facultative = False
Access and print the content of specific script lines/items
print(S[3]) # Outputs: instruction .... with substitution rules ${v1}+${var2} print(S['alpha']) # Outputs: another script template ${v3}
Access and print custom attributes
print(S[3].attribute1) # Outputs: True
Iterate through all script lines, printing their keys and content
for key, content in S.items(): print(f"Key: {key}, Content: {content}")
Retrieve and evaluate the content of a script line by its index
S.get_content_by_index(0, False) # Retrieve without evaluation S.get_content_by_index(0) # Retrieve with evaluation
Access attributes of a specific script line by index
S.get_attributes_by_index(0)
Apply conditions to the execution of a script line
S[0].condition = "$a>1" S[0].condeval = True S.get_content_by_index(2) # Condition not met, may result in an empty string
Update the condition and evaluate again
S[0].condition = "$a>0" S[0].do() # Executes and evaluates the line content
Create multiple variables in DEFINITIONS if they don't already exist
S.createEmptyVariables(["a", "b", "c", "d", "e"])
Access and print all current definitions
S.DEFINITIONS
=====================================================
Production Example: LAMMPS Header Initialization
closely related to pizza.region.LammpsHeaderInit
=====================================================
Initialize a dscript object with a custom name
R = dscript(name="ProductionExample")
Define global variables (DEFINITIONS) for the script
R.DEFINITIONS.dimension = 3 R.DEFINITIONS.units = "$si" R.DEFINITIONS.boundary = ["sm", "sm", "sm"] R.DEFINITIONS.atom_style = "$smd" R.DEFINITIONS.atom_modify = ["map", "array"] R.DEFINITIONS.comm_modify = ["vel", "yes"] R.DEFINITIONS.neigh_modify = ["every", 10, "delay", 0, "check", "yes"] R.DEFINITIONS.newton = "$off"
Define the script template, associating each line with a key
R[0] = "% ${comment}" # line/item can be identied by numbers/names R["dim"] = "dimension ${dimension}" # line/item identified as 'dim' R["unit"] = "units ${units}" # line/item identified as 'unit' R["bound"] = "boundary ${boundary}" R["astyle"] = "atom_style ${atom_style}" R["amod"] = "atom_modify ${atom_modify}" R["cmod"] = "comm_modify ${comm_modify}" R["nmod"] = "neigh_modify ${neigh_modify}" R["newton"] = "newton ${newton}"
Apply a condition to the 'astyle' line
it will only be included if ${atom_style} is defined
R["astyle"].condition = "${atom_style}"
Update DEFINITIONS to unset the atom_style variable
R.DEFINITIONS.atom_style = ""
Generate a script instance, overwriting the 'units' variable and adding a comment
sR = R.script(units="$lj", # Use "$" to prevent immediate evaluation comment="$my first dynamic script")
Execute the script to generate the final content
ssR = sR.do()
Print the generated script
print(ssR)
Save the current script
R.save(overwrite=True)
Load again the same script and show the script
T = dscript.load(R.name) print(repr(T)) ssT = R.script(units="$lj", # Use "$" to prevent immediate evaluation comment="$my second dynamic script").do() print(ssT)
The script is defined here within a string
note that the first line should be: # DSCRIPT SAVE FILE
myscript = """# DSCRIPT SAVE FILE
Global Parameters:
------------------
Define general settings for the script class.
This section is not mandatory.
Properties are defined within { }
They include
SECTIONS = ["DYNAMIC"] # the considered section names
section = 0 # the current section index,
position = 0 # the script position order,
role = "dscript instance",
description = "dynamic script",
userid = "dscript",
version = 0.1,
verbose = False
{ # a line starting with { indicates the begining of the section SECTIONS = ['INITIALIZATION', 'SIMULATION'], # this is a comment section=0, position=0 } # note the closing } is mandatory
DEFINITIONS (Define general settings for the script.)
-----------
All variables are defined in a Python way
d = 3 # d is a number and equals 3 units = "$lj" # $ is used to block immediate execution in a string periodic = "$p" # $ is used to block immediate execution in a string dimension = "${d}" # d is a variable boundary = ["p", "p", "p"] # this a list (Python syntax) atom_style = "$atomic" lattice = ["fcc", 3.52] # this a list (Python syntax) region = ["box", "block", 0, 10, 0, 10, 0, 10] # this a list (Python syntax) create_box = [1, "box"] create_atoms = [1, "box"] mass = 1.0 pair_style = ["lj/cut", 2.5] pair_coeff = [1, 1, 1.0, 1.0, 2.5] velocity = ["all", "create", 300.0, 12345] fix = [1, "all", "nve"] run = 1000 timestep = 0.001 thermo = 100
TEMPLATE:
---------
Provide a template for how these parameters should be formatted or used in the script.
The general syntax is:
KEY: INSTRUCTION
KEY can be numeric, alphanumeric
INSTRUCTION can be any LAMMPS command involving variables defined in the DEFINITION section or elsewhere
units: units ${units} # key = units, template = units ${units} dim: dimension ${dimension} bound: boundary ${boundary} astyle: atom_style ${atom_style} lattice: lattice ${lattice} region: region ${region} create_box: create_box ${create_box} create_atoms: create_atoms ${create_atoms} mass: mass ${mass} pair_style: pair_style ${pair_style} pair_coeff: pair_coeff ${pair_coeff} velocity: velocity ${velocity} fix: fix ${fix} run: run ${run} timestep: timestep ${timestep} thermo: thermo ${thermo}
Attributes:
-----------
Each template line can have attributes (here default attributes, but the user can add more)
Default value between ()
facultative = True or (False) (remove the template line if True)
eval = True or (False) (evaluate the template line with eval() if True)
readonly True or (False) (prevent any subsequent modification() if True)
condition = any expression with variables
condeval = True or (False) (evaluate the condition with eval() if True)
detectvar = (True) or False (create variables in DEFINITIONS if True)
units: {facultative=False, eval=False, readonly=False, condition="${units}", condeval=False, detectvar=True} dim: {facultative=False, eval=False, readonly=False, condition=None, condeval=False, detectvar=True}
# write myscript to disk
myscriptfile = dscript.write(myscript)
print(f"DSCRIPT SAVE FILE: {myscriptfile}")
# load the script as a dscript object
myS = dscript.load(myscriptfile)
# generate the corresponding script
myS.units.do()
smyS = myS.script()
# Ececute the script and print it
ssmyS = smyS.do()
print(ssmyS)
# The conversion of a string into a script
# can be mediated via dscript.parsesyntax()
# without using a temporary file
mytemplate = dscript.parsesyntax(myscript).script()
mytemplatetxt = mytemplate.do()
print(mytemplatetxt)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Beyond this line, the previous examples are tested with the new compact syntax
# enabling to define a template-block with a single key/tag.
# The intent is to accelerate scripting and readability.
#
# IMPORTANT
# In DSCRIPT SAVE FILE, a block uses a new syntax between square brackets "[]"
# # TEMPLATE (number of items=1)
# code: [
# % ${comment}
# dimension ${dimension}
# units ${units}
# boundary ${boundary}
# atom_style ${atom_style}
# atom_modify ${atom_modify}
# comm_modify ${comm_modify}
# neigh_modify ${neigh_modify}
# newton ${newton}
# ]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
#
# =====================================================
# Production Example version 2: compact version
# using multiple lines/items template
# =====================================================
R2 = dscript(name="ProductionExample2")
# Define global variables (DEFINITIONS) for the script
R2.DEFINITIONS.dimension = 3
R2.DEFINITIONS.units = "$si"
R2.DEFINITIONS.boundary = ["sm", "sm", "sm"]
R2.DEFINITIONS.atom_modify = ["map", "array"]
R2.DEFINITIONS.comm_modify = ["vel", "yes"]
R2.DEFINITIONS.neigh_modify = ["every", 10, "delay", 0, "check", "yes"]
R2.DEFINITIONS.newton = "$off"
# Define the script template, associating each line with a key
R2["code"] =
% ${comment} # this comment will be preserved as it starts with % dimension ${dimension} # this comment will be deleted units ${units} boundary ${boundary} atom_style ${atom_style} atom_modify ${atom_modify} comm_modify ${comm_modify} neigh_modify ${neigh_modify} newton ${newton}
write myscript to disk
myscriptfile2 = dscript.write(myscript2) print(f"DSCRIPT SAVE FILE: {myscriptfile2}")
load the script as a dscript object
myS2 = dscript.load(myscriptfile2)
generate the corresponding script
smyS2 = myS2.script()
Ececute the script and print it
ssmyS2 = smyS2.do() print(ssmyS2)
The conversion of a string into a script
can be mediated via dscript.parsesyntax()
without using a temporary file
mytemplate2 = dscript.parsesyntax(myscript2).script() mytemplatetxt2 = mytemplate2.do() print(mytemplatetxt2)
This flexible approach enables dynamic manipulation of simulation parameters.
The full TLSPH template is defined as a multi-line script in DSCRIPT format.
The following template was automatically generated by ChatGPT based on the
original LAMMPS TLSPH simulation script for elongating a 2D strip of linear
elastic material by pulling its ends apart.
Key variables (such as Young's modulus, Poisson's ratio, and mass density)
have been added to the DEFINITIONS section for dynamic substitution in the
template.
Read the synopsis of this module to learn how to instruct ChatGPT to generate
such templates.
TLSPH_template = """# DSCRIPT SAVE FILE
TENSILE SUMULATION
TLSPH example: elongate a 2d strip of a linear elastic material py pulling its ends apart
unit sytem: GPa / mm / ms
Source:
GLOBAL PARAMETERS
{ SECTIONS = ['INITIALIZE', 'CREATE_GEOMETRY', 'DISCRETIZATION', 'BOUNDARY_CONDITIONS', 'PHYSICS', 'OUTPUT', 'RUN'], section = 0, position = 0, role = "dscript instance", description = "Advanced example based on ChatGPT translation", userid = "ChatGPT", version = 1.0, verbose = False }
DEFINITIONS (number of definitions=12)
E=1.0 # Young's modulus nu=0.3 # Poisson ratio rho=1.0 # Initial mass density q1=0.06 # Artificial viscosity linear coefficient q2=0.0 # Artificial viscosity quadratic coefficient hg=10.0 # Hourglass control coefficient cp=1.0 # Heat capacity l0=1.0 # Lattice spacing h=2.01 * ${l0} # SPH smoothing kernel radius vol_one=${l0}**2 # Volume of one particle (unit thickness) vel0=0.005 # Pull velocity skin=${h} # Verlet list range
TEMPLATE (number of lines=8)
initialize: [ dimension 2 units si boundary sm sm p atom_style smd atom_modify map array comm_modify vel yes neigh_modify every 10 delay 0 check yes newton off ]
set region dimensions
boxlength = 10 # variables can be defined and changed any time (only the last definition is retained) boxdepth = 0.1 # variables can be defined and changed any time (only the last definition is retained) create: [ lattice sq ${l0} region box block ${boxlength} ${boxlength} ${boxlength} ${boxlength} ${boxdepth} ${boxdepth} units box create_box 1 box create_atoms 1 box group tlsph type 1 ] discretization: [ neighbor ${skin} bin set group all volume ${vol_one} set group all smd_mass_density ${rho} set group all diameter ${h} ] boundary_conditions: [ region top block EDGE EDGE 9.0 EDGE EDGE EDGE units box region bot block EDGE EDGE EDGE 9.1 EDGE EDGE units box group top region top group bot region bot variable vel_up equal ${vel0} * (1.0 exp(0.01 * time)) variable vel_down equal v_vel_up fix veltop_fix top smd/setvelocity 0 v_vel_up 0 fix velbot_fix bot smd/setvelocity 0 v_vel_down 0 ] physics: [ pair_style smd/tlsph pair_coeff 1 1 *COMMON ${rho} ${E} ${nu} ${q1} ${q2} ${hg} ${cp} & *STRENGTH_LINEAR & *EOS_LINEAR & *END ] output: [ compute S all smd/tlsph_stress compute E all smd/tlsph_strain compute nn all smd/tlsph_num_neighs dump dump_id all custom 10 dump.LAMMPS id type x y z vx vy vz & c_S[1] c_S[2] c_S[4] c_nn & c_E[1] c_E[2] c_E[4] & vx vy vz dump_modify dump_id first yes ]
add filename
outputfilename = "$stress_strain.dat" # variables can be defined and changed any time status_output: [ variable stress equal 0.5 * (f_velbot_fix[2] - f_veltop_fix[2]) / 20 variable length equal xcm(top,y) - xcm(bot,y) variable strain equal (v_length - ${length}) / ${length} fix stress_curve all print 10 "${strain} ${stress}" file ${outputfilename} screen no thermo 100 thermo_style custom step dt f_dtfix v_strain ]
add runtime
runtime = 2000 # variables can be defined and changed any time
single liner template
run_simulation: run ${runtime}
change runtime
runtime = 2500 # variables can be defined and changed any time (only the last definition is retained)
X = dump("../issues/time/dump.vwall_0.01")
f1 = "../data/play_data/dump.play.1frames" f2 = "../data/play_data/dump.play.50frames" X1 = dump(f1) X1.kind() X1.type X50 = dump(f2) X50.kind() X50.type X = X50 + X1 xy=X.vecs(82500,('x','y'))
try:
Example usage
datafile1 = "../data/play_data/dump.play.1frames" datafile2 = "../data/play_data/dump.play.50frames" X1 = dump(datafile1) X1_kind = X1.kind() X1_type = X1.type X50 = dump(datafile2) X50_kind = X50.kind() X50_type = X50.type X = X50 + X1 xy = X.vecs(82500, 'x', 'y') logger.info(f"Extracted vectors: {xy}") except Exception as e: logger.error(f"An error occurred during execution: {e}") sys.exit(1)
w = water(beadtype=1, userid="fluid") w.parameters.Cp = 20 print("\n"*2,w) f = solidfood(beadtype=2, userid="elastic") print("\n"*2,f) r = rigidwall(beadtype=3, userid="wall") print("\n"*2,r)
mylibrary = USERSMD(name="currentsim",h=1) w = mylibrary.newtonianfluid(beadtype=1, userid="fluid") print("\n"*2,w)
Example Usage
G = group() G.variable("groupname","variablename","myexpression myexpression myexpression myexpression and again 1234") print(G.disp("groupname")) G.byregion("regiongroup","myregionID") print(G.disp("regiongroup")) G.union("uniongroup","group1","group2","group3") print(G.disp("uniongroup"))
LAMMPS example
group myGroup region myRegion
group typeGroup type 1 2
variable myVar atom "x + y"
group varGroup variable myVar
group unionGroup union myGroup typeGroup
Assuming Operation class is properly defined and includes necessary methods
G0 = group() G0.byregion('myGroup', 'myRegion') G0.bytype('typeGroup', [1, 2]) G0.variable('myVar', 'x + y') G0.byvariable('varGroup', 'myVar')
Perform group operations
union_op = G0['myGroup'] + G0['typeGroup'] G0.evaluate('unionGroup', union_op)
Generate LAMMPS script
print(G0.code())
Advanced Usage
G = group() G.create_groups('o1', 'o2', 'o3', 'o4') G.create('o5') G.create('o6') G.create('o7') G.evaluate("debug0",G.o1+G.o2+G.o3 + G.o4 + (G.o5 +G.o6) + G.o7) G.evaluate("debug1",G.o1+G.o2) G.evaluate("debug2",G.o1+G.o2+G.o3-(G.o4+G.o5)+(G.o6*G.o7)) print(repr(G))
Example to prepare workshop
G = group() G.add_group_criteria("lower", type=[1]) G.add_group_criteria("central", region="central_cyl") G.add_group_criteria("new_group", create=True) G.add_group_criteria("upper", clear=True) G.add_group_criteria("subtract_group", subtract=["group1", "group2"])
=============================================================================
# very advanced
import os
from fitness.private.loadods import alias
local = "C:/Users/olivi/OneDrive/Data/Olivier/INRA/Etudiants & visiteurs/Steward Ouadi/python/test/output/"
odsfile = "fileid_conferences_FoodRisk.ods"
fullfodsfile = os.path.join(local,odsfile)
p = alias(fullfodsfile)
p.disp()
=============================================================================
new feature
a = struct(a=1,b=2) a["b"]
path example
s0 = struct(a=pstr("/tmp/"),b=pstr("test////"),c=pstr("${a}/${b}"),d=pstr("${a}/${c}"),e=pstr("$c/$a")) s = struct.struct2param(s0,protection=True) s.disp() s.a/s.b str(pstr.topath(f"{s.a}/{s.b}")) s.eval()
escape example
definitions = param(a=1,b="${a}*10+${a}",c=r"\${a}+10",d=r'\${myparam}') text = definitions.formateval(r"this my text ${a}, ${b}, \${myvar}=${c}+${d}") print(text) definitions = param(a=1,b="$a*10+$a",c=r"\$a+10",d=r'\$myparam') text = definitions.formateval(r"this my text $a, $b, \$myvar=$c+$d",protection=True) print(text)
assignment
s = struct(a=1,b=2) s[1] = 3 s.disp()
conversion
s = {"a":1, "b":2} t=struct.dict2struct(s) t.disp() sback = t.struct2dict() sback.__repr__()
file definition
p=struct.fromkeysvalues(["a","b","c","d"],[1,2,3]).struct2param() ptxt = p.protect("$c=$a+$b") definitions.write("../../tmp/test.txt")
populate/inherit fields
default = struct(a=1,b="2",c=[1,2,3]) tst = struct(a=10) tst.check(default) tst.disp()
multiple assigment
a = struct(a=1,b=2,c=3,d=4) b = struct(a=10,b=20,c=30,d=40) a[:2] = b[1:3] a[:2] = b[(1,3)]
reorganize definitions to enable param.eval()
s = param( a = 1, f = "${e}/3", e = "${a}*${c}", c = "${a}+${b}", b = 2, d = "${c}*2" )
s[0:2] = [1,2]
s.isexpression struct.isstrdefined("${a}+${b}",s) s.isdefined() s.sortdefinitions() s.disp() p = param(b="${a}+1",c="${a}+${d}",a=1) p.disp()
features 2025
p=param() p.a = [0,1,2] p.b = '![1,2,"test","${a[1]}"]' p
Mathematical expressions
Example: param.safe_fstring()
Sample context with a NumPy array
context = param( f = np.array([ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16] ]) )
Example expressions
expressions = [ "${a[1]}", # Should return 0.2 (assuming 'a' is defined in context) "${b[0,1]} + ${a[0]}", # Should return 1.2 (assuming 'b' and 'a' are defined) "${f[0:2,1]}" # Should return the second column of 'f' ]
Assuming 'a' and 'b' are defined in the context
context.update( a =[1.0, 0.2, 0.03, 0.004], b = np.array([[1, 0.2, 0.03, 0.004]]) ) for expr in expressions: result = param.safe_fstring(expr, context) print(f"Expression: {expr} => Result: {result}")
Example with matrix operations
p=param() p.a = [1.0, .2, .03, .004] p.b = np.array([p.a]) p.c = p.a*2 p.d = p.b*2 p.e = p.b.T p.f = p.b.T@p.b # Matrix multiplication for (3x1) @ (1x3) p.g = "${a[1]}" p.h = "${b[0,1]} + ${a[0]}" p.i = "${f[0,1]}" p.j = "${f[:,1]}" p.k = "@{j}+1" # note that "@{j}+1" and "${j}+1" do not have the same meaning p.l = "${b.T}" p.m = "${b.T @ b}" # evaluate fully the matrix operation p.n = "${b.T} @ ${b}" # concatenate two string-results separated by @ p.o ="the result is: ${b[0,1]} + ${a[0]}" p.p = "the value of a[0] is ${a[0]}" p.q = "1+1" print(repr(p))
Example with new NumPy shorthands
p = param(debug=True); p.a = 1.0 p.b = "10.0" p.c = "$[${a},2,3]*${b}" # Create a Numpy vector from an operation p.n = "$[0,0,1]" # another one p.o1 = "@{n}" # create a copy p.o2 = "$[${a},2,3]" # create a Numpy vector p.o3 = "@{o1} @ @{o2}.T" # multiplication between two vectots p.d = "@{n}.T @ $[[${a},2,3]]" # another one p.f = "($[${a},2,3]*${b}) @ np.array([[0,0,1]]).T" # another one using explicitly NumPy p.nT = "@{n}.T" # transpose of a vector/matrix p.m = "${n.T}*2" # this operation is illegal and will be kept as a string p.o = "@{n}.T*2" # this one is the correct one p.p = "$[[1,2],[3,4]]" # Create a 2D Numpy array p.q = "${p[1,1]}" # index a 2D NumPy array p.r = "${p[:,1]}" # this is a valid syntax to get the slice as a list p.s = "@{p}[:,1]+1" # use this syntax if you need apply an operation to the slice
more advanced
p.V1 = "$[1.0,0.2,0.03]" p.V2 = "@{V1}+1" p.V3 = "@{V1}.T @ @{V2}" p.V4 = "np.diag(@{V3})" p.V5 = "np.linalg.eig(@{V3})" p.out = "the first eigenvalue is: ${V5.eigenvalues[0]}" print(repr(p))
Advanced NumPy example
p = param(debug=True) p.p = "$[[1, 2], [3, 4]]" # Create a 2D NumPy array p.q = "${p[1, 1]}" # Indexing: retrieves 4 p.r = "@{p}[:,1] + 1" # Add 1 to the second column p.s = "@{p}[:, 1].reshape(-1, 1) @ @{r}" # perform p(:,1)'*s in Matlab sense p.t = "np.linalg.eig(@{s})" p.w = "${t.eigenvalues[0]} + ${t.eigenvalues[1]}" # sum of eigen values p.x = "$[[0,${t.eigenvalues[0]}+${t.eigenvalues[1]}]]" # horizontal concat à la Matlab print(repr(p))
%% Math example with DSCRIPT (pending) - v 1.005
from pizza.dscript import dscript from pizza.private.mstruct import param D = dscript(name="math example")
The definitions are given with hybrid Matlab/NumPy notations
D.DEFINITIONS.l = [1e-3, 2e-3, 3e-3] # l is defined as a list D.DEFINITIONS.a = "$[1 2 3]" # a is defined with Matlab notations D.DEFINITIONS.b = "$[1:3]" # b is defined with Matlab notations D.DEFINITIONS.c = "$[0.1:0.1:0.9]" # c is defined with Matlab notations D.DEFINITIONS.scale = "@{l}*2*@{a}" # l is rescaled D.DEFINITIONS.x0 = "$[[[-0.5, -0.5],[-0.5, -0.5]],[[ 0.5, 0.5],[ 0.5, 0.5]]]*${scale[0,0]}*${a[0,0]}" D.DEFINITIONS.y0 = "$[[[-0.5, -0.5],[0.5, 0.5]],[[ -0.5, -0.5],[ 0.5, 0.5]]]*${scale[0,1]}*${a[0,1]}" D.DEFINITIONS.z0 = "$[[-0.5 0.5 ;-0.5 0.5],[ -0.5, 0.5; -0.5, 0.5]]*${l[2]}*${a[0,2]}" D.DEFINITIONS.X0 = "@{x0}.flatten()" D.DEFINITIONS.Y0 = "@{y0}.flatten()" D.DEFINITIONS.Z0 = "@{z0}.flatten()" T = D.DEFINITIONS.eval() D.DEFINITIONS.x0 T.x0 print(repr(D.DEFINITIONS))
updatepptx()
%% basic example
plt.close("all") R = raster() R.rectangle(1,24,2,20,name='rect1') R.rectangle(60,80,50,81,name='rect2',beadtype=2,angle=40,beadtype2=(9,0.2)) R.rectangle(50,50,10,10,mode="center",angle=45,beadtype=1) R.circle(45,20,5,name='C1',beadtype=3,beadtype2=(8,0.25)) R.circle(35,10,5,name='C2',beadtype=3) R.circle(15,30,10,name='p1',beadtype=4,shaperatio=0.2,angle=-30) R.circle(12,40,8,name='p2',beadtype=4,shaperatio=0.2,angle=20) R.circle(12,80,22,name='p3',beadtype=4,shaperatio=1.3,angle=20,beadtype2=(9,0.1)) R.triangle(85,20,10,name='T1',beadtype=5,angle=20) R.diamond(85,35,5,name='D1',beadtype=5,angle=20,beadtype2=(9,0.5)) R.pentagon(50,35,5,name='P1',beadtype=5,angle=90) R.hexagon(47,85,12,name='H1',beadtype=5,angle=90) R.label("rect003") R.plot() R.list() R.show() R.clear() R.show() R.plot() R.show(extra="label") R.label("rect003") R.unlabel('rect1') X=R.data()
%% another example
S = raster(width=1000,height=1000) S.rectangle(150,850,850,1000,name="top",beadtype=1) S.rectangle(150,850,0,150,name="bottom",beadtype=2) S.circle(500,500,480,name="mask",ismask=True,resolution=500) S.triangle(250,880,80,name='tooth1',angle=60,beadtype=1) S.triangle(750,880,80,name='tooth2',angle=-0,beadtype=1) S.circle(500,200,300,name="tongue",beadtype=5,shaperatio=0.3,resolution=300) S.rectangle(500,450,320,320,name="food",mode="center",beadtype=3) S.plot() S.show(extra="label",contour=False)
%% advanced example
plt.close("all")
draft = raster() draft.rectangle(1,24,2,20,name='rect1'), draft.rectangle(60,80,50,81,name='rect2',beadtype=2,angle=40), draft.rectangle(50,50,10,10,mode="center",angle=45,beadtype=1), draft.circle(45,20,5,name='C1',beadtype=3), draft.circle(35,10,5,name='C2',beadtype=3), draft.circle(10,10,2,name="X",beadtype=4) A = raster() A.collection(draft,name="C1",beadtype=1,translate=[10,30]) repr(A) A.objects A.plot() A.show(extra="label") A.objects B = raster()
B.collection(X=draft.X,beadtype=1,translate=[50,50])
B.copyalongpath(draft.X,name="PX",beadtype=2, path=arc, xmin=10, ymin=10, xmax=90, ymax=50, n=12) B.plot() B.show(extra="label")
%% emulsion example
C = raster(width=400,height=400) e = emulsion(xmin=10, ymin=10, xmax=390, ymax=390) e.insertion([60,50,40,30,20,15,15,10,8,20,12,8,6,4,11,13],beadtype=1) e.insertion([30,10,20,2,4,5,5,10,12,20,25,12,14,16,17],beadtype=2) e.insertion([40,2,8,6,6,5,5,2,3,4,4,4,4,4,10,16,12,14,13],beadtype=3) C.scatter(e,name="emulsion") C.plot() C.show()
%% core-shell example
D = raster(width=400,height=400) cs = coreshell(xmin=10, ymin=10, xmax=390, ymax=390) cs.insertion([60,50,40,30,20,15,15,10,8,20,12,8,11,13],beadtype=(1,2),thickness = 4) D.scatter(cs,name="core-shell") D.plot() D.show()
%% overlay example
I = raster(width=600,height=600) I.overlay(30,100,name="pix0",filename="./sandbox/image.jpg",ncolors=4,color=0,beadtype=1,angle=10,scale=(1.1,1.1)) I.overlay(30,100,name="pix2",filename="./sandbox/image.jpg",ncolors=4,color=2,beadtype=2,angle=10,scale=(1.1,1.1)) I.label("pix0") I.plot() I.show(extra="label") I.pix0.original I.pix0.raw a = I.torgb("objindex",(512,512)) a.show() a.save("./tmp/preview.png")
R = region(name="my region", mass=2, density=5)
Create a Block object using the block method of the region container with specific dimensions
R.block(xlo=0, xhi=10, ylo=0, yhi=10, zlo=0, zhi=10, name="B1",mass=3)
Access the natoms property of the Block object
print("Number of atoms in the block:", R.B1.natoms)
early example
a=region(name="region A") b=region(name="region B") c = [a,b]
step 1
R = region(name="my region") R.ellipsoid(0, 0, 0, 1, 1, 1,name="E1",toto=3) R repr(R.E1) R.E1.VARIABLES.a=1 R.E1.VARIABLES.b=2 R.E1.VARIABLES.c="(${a},${b},100)" R.E1.VARIABLES.d = '"%s%s" %("test",${c}) # note that test could be replaced by any function' R.E1 code1 = R.E1.do() print(code1)
step 2
R.ellipsoid(0,0,0,1,1,1,name="E2",side="out",move=["left","${up}*3",None],up=0.1) R.E2.VARIABLES.left = '"swiggle(%s,%s,%s)"%(${a},${b},${c})' R.E2.VARIABLES.a="${b}-5" R.E2.VARIABLES.b=5 R.E2.VARIABLES.c=100 code2 = R.E2.do() print(R) repr(R.E2) print(code2) print(R.names) R.list()
eval objects
R.set('E3',R.E2) R.E3.beadtype = 2 R.set('add',R.E1 + R.E2) R.addd2 = R.E1 + R.E2 R.eval(R.E1 | R.E2,'E12')
How to manage pipelines
print("\n","-"*20,"pipeline","-"*20) p = R.E2.script s = p.script() # first execution s = p.script() # do nothing s # check
reorganize scripts
print("\n","-"*20,"change order","-"*20) p.clear() # undo executions first q = p[[0,2,1]] sq = q.script() print(q.do())
join sections
liste = [x.SECTIONS["variables"] for x in R] pliste = pipescript.join(liste)
Example closer to production
P = region(name="live test",width = 20) P.ellipsoid(0, 0, 0, "${Ra}", "${Rb}", "${Rc}", name="E1", Ra=5,Rb=2,Rc=3) P.sphere(7,0,0,radius="${R}",name = "S1", R=2) cmd = P.do() print(cmd)
EXAMPLE: gel compression
scale = 1 name = ['top','food','tongue','bottom'] radius = [10,5,8,10] height = [1,4,3,1] spacer = 2 * scale radius = [r*scale for r in radius] height = [h*scale for h in height] position_original = [spacer+height[1]+height[2]+height[3], height[2]+height[3], height[3], 0] beadtype = [1,2,3,1] total_height = sum(height) +spacer position = [x-total_height/2 for x in position_original] B = region(name = 'region container', width=2*max(radius), height=total_height, depth=2*max(radius)) for i in range(len(name)): B.cylinder(name = name[i], c1=0, c2=0, radius=radius[i], lo=position[i], hi=position[i]+height[i], beadtype=beadtype[i]) B.dolive()
Draft for workshop
sB = B.do() b1 = B[0].scriptobject() b2 = B[1].scriptobject() b3 = B[2].scriptobject() b4 = B[3].scriptobject() collection = b1 + b2 + b3 + b4;
# emulsion example
scale = 1 # tested up to scale = 10 to reach million of beads mag = 3 e = emulsion(xmin=-5*mag, ymin=-5*mag, zmin=-5*mag,xmax=5*mag, ymax=5*mag, zmax=5*mag) e.insertion([2,2,2,1,1.6,1.2,1.4,1.3],beadtype=3) e.insertion([0.6,0.3,2,1.5,1.5,1,2,1.2,1.1,1.3],beadtype=1) e.insertion([3,1,2,2,4,1,1.2,2,2.5,1.2,1.4,1.6,1.7],beadtype=2) e.insertion([3,1,2,2,4,1,5.2,2,4.5,1.2,1.4,1.6,1.7],beadtype=4)
b = region()
a = region()
a.sphere(1,1,1,1,name='sphere1')
a.sphere(1,2,2,1,name='sphere2')
b.collection(a, name='acollection')
C = region(name='cregion',width=11*mag,height=11*mag,depth=11*mag) C.scatter(e) C.script() g = C.emulsion.group() C.dolive()
EXAMPLE: gel compression with SI units
name = ['top', 'food', 'tongue', 'bottom'] radius = [10e-3, 5e-3, 8e-3, 10e-3] # in m height = [1e-3, 4e-3, 3e-3, 1e-3] # in m spacer = 2e-3 # in m
Calculate positions in SI units (meters)
position_original = [ spacer + height[1] + height[2] + height[3], height[2] + height[3], height[3], 0 ] total_height = sum(height) + spacer * 1e-3 # converting spacer to meters
Center positions around the middle of the container
position = [x - total_height / 2 for x in position_original]
information for beads
add attributes to forcefields to match your needs or derive new forcefields
beadtypes = [1, 2, 3, 1] groups = [["rigid","wall1"],["food1","soft"],["food2","soft"],["rigid","wall2"]] forcefields = [rigidwall(),solidfood(),solidfood(),rigidwall()]
Create the region container with SI units
R = region( name='region container', width=2 * max(radius), height=total_height, depth=2 * max(radius), regionunits="si", separationdistance=100e-6, # 50 µm lattice_scale=100e-6 # 50 µm )
Add cylinders to the region R
the objects are added "statically"
since they contain variables a do() is required to make them a script
nobjects = len(name) for i in range(nobjects): R.cylinder( name=name[i], dim="z", # Assuming z-axis as the dimension c1=0, c2=0, radius=radius[i], lo=position[i], hi=position[i] + height[i], beadtype=beadtypes[i], style="smd", # the script oject properties group=groups[i], # can be defined in the geometry or forcefield=forcefields[i] # when scriptoject() is called )
Compile statically all objects
sR contains the LAMMPS code to generate all region objects and their atoms
sR is a string, all variables have been executed
sR = R.do() # this line force the execution of R
Header Scripts facilitate the deployment and initialization of region objects.
------------- Summary ---------------
Available scripts include "init", "lattice", and "box".
Multiple scripts can be generated simultaneously by specifying them in a list.
For example: ["init", "lattice", "box"] will generate all three scripts.
Script parameters and variables can be customized via R.headersData.
For instance: R.headersData.lattice_style = "$sq"
This overrides the lattice style, which was originally set in the region object.
The "$" prefix indicates that lattice_style is a static value.
Alternatively, R.headersData.lattice_style = ["sq"] can also be used.
--------------------------------------
use help(R.scriptHeaders) to get a full help
Note: sRheader is a string since a do()
sRheader = R.scriptHeaders("box").do() # generate the box that contains R print(sRheader)
To generate all header scripts in the specified order, use R.scriptHeaders.
Note: sRallheaders is a script object. Use sRallheaders.do() to convert it into a string.
Scripts can be dynamically combined using the + operator or statically with the & operator.
Scripts can also be combined with pipescripts using the + or | (piped) operator.
Region and collection objects are considered pipescripts.
Comment on the differences between scripts and pipescripts:
- Scripts operate within a single variable space and cannot be reordered once combined.
- Pipescripts, however, include both global and local variable spaces and can be reordered,
and indexed, offering greater flexibility in complex simulations.
A property can be removed from the initialization process by setting it to None or ""
In this example, atom_style is removed as it also set with forcefields
R.headersData.atom_style = None sRallheaders = R.scriptHeaders(["init", "lattice", "box"] )
Generate information on beads from the scripted objects
note that scriptobject is a method of script extended to region
the region must have been preallably scripted, which has been done with "sR = R.do()"
Note that the current implementation include also style definitions in init
b = [] for i in range(nobjects):
style, group and forcefield can be overdefined if needed
b.append(R[i].scriptobject(style="smd")) collection = b[0] + b[1] + b[2] + b[3]
The script corresponding to the collection is given by:
scollection is an object of the class script
its final execution can be still affected by variables
scollection = collection.script.do()
Execute the region setup only for visualization (control only)
R.dolive()
The detail of the geometry with an estimation of the number of atoms (control only)
R.geometry
example of scriptobject()
b1 = scriptobject(name="bead 1",group = ["A", "B", "C"],filename='myfile1',forcefield=rigidwall()) b2 = scriptobject(name="bead 2", group = ["B", "C"],filename = 'myfile1',forcefield=rigidwall()) b3 = scriptobject(name="bead 3", group = ["B", "D", "E"],forcefield=solidfood()) b4 = scriptobject(name="bead 4", group = "D",beadtype = 1,filename="myfile2",forcefield=water()) collection = b1+b2+b3+b4 grp_typ1 = collection.select(1) grpB = collection.group.B collection.interactions
main example of script()
G = globalsection() print(G) c = initializesection() print(c) g = geometrysection() print(g) d = discretizationsection() print(d) b = boundarysection() print(b) i = interactionsection() print(i) t = integrationsection() print(t) d = dumpsection() print(d) s = statussection() print(s) r = runsection() print(r)
# all sections as a single script
myscript = G+c+g+d+b+i+t+d+s+r p = pipescript() p | i p = collection | G p | i p[0] q = p | p q[0] = [] p[0:1] = q[0:1] print("\n"*4,'='*80,'\n\n this is the full script\n\n','='*80,'\n') print(myscript.do())
pipe full demo
p = G | c | g | d | b | i | t | d | s | r p.rename(["G","c","g","d","b","i","t","d","s","r"]) cmd = p.do([0,1,4,7]) sp = p.script([0,1,4,7]) r = collection | p p[0:2]=p[0]*2