Skip to content

Commit

Permalink
refactor translation to pypicongpu
Browse files Browse the repository at this point in the history
  • Loading branch information
BrianMarre committed Jul 29, 2024
1 parent 60d47e6 commit 60817b9
Show file tree
Hide file tree
Showing 23 changed files with 802 additions and 422 deletions.
3 changes: 2 additions & 1 deletion lib/python/picongpu/picmi/interaction/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .interactioninterface import InteractionInterface
from .interaction import Interaction
from . import ionization

__all__ = ["Interaction", "ionization"]
__all__ = ["InteractionInterface", "Interaction", "ionization"]
118 changes: 114 additions & 4 deletions lib/python/picongpu/picmi/interaction/interaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
License: GPLv3+
"""

import pydantic
from .ionization import IonizationModel
from ... import pypicongpu

from .ionization.groundstateionizationmodel import GroundStateIonizationModel
from .interactioninterface import InteractionInterface
from ..species import Species

class Interaction(pydantic.BaseModel):
import picmistandard


class Interaction(InteractionInterface):
"""
Common interface of Particle-In-Cell particle interaction extensions
Expand All @@ -19,7 +24,7 @@ class Interaction(pydantic.BaseModel):
It does not specify interface requirements for sub classes, since they differ too much.
"""

Ionization: list[IonizationModel]
ground_state_ionization_model_list: list[GroundStateIonizationModel]
"""
list of all interaction models that change the charge state of ions
Expand All @@ -28,3 +33,108 @@ class Interaction(pydantic.BaseModel):
"""

# @todo add Collisions as elastic interaction model, Brian Marre, 2024

@staticmethod
def update_constant_list(
existing_list: list[pypicongpu.species.constant.Constant],
new_list: dict[str, pypicongpu.species.constant.Constant],
) -> None:
"""check if dicts may be merged without overwriting previously set values"""

new_constant_list = []

for constant_new in new_list:
exists_already = False
for constant in existing_list:
if type(constant) == type(constant_new):
# constant_new already exists in existing constants list
exists_already = True

if constant != constant_new:
# same type of constant but conflicting values
raise ValueError(f"Constants {constant} and {constant_new} conflict with each other")

if not exists_already:
new_constant_list.append(constant_new)
# ignore already existing constants

# update constant_list
existing_list.extend(new_constant_list)

def get_interaction_constants(
self, species: picmistandard.PICMI_Species
) -> list[pypicongpu.species.constant.Constant]:
"""get list of all constants required by interactions for the given species"""

constant_list = []
ground_state_model_conversion = {}
for model in self.ground_state_ionization_model_list:
if model.ion_species == Species:
model_constants = model.get_constants()
Interaction.update_constant_list(constant_list, model_constants)

ground_state_model_conversion[model] = model.get_as_pypicongpu()

# add GroundStateIonization constant for entire species
constant_list.append(
pypicongpu.species.constant.GroundStateIonization(
ground_state_ionization_model_list=ground_state_model_conversion.values()
)
)

# add additional interaction sub groups needing constants here
return constant_list, {"ground_state_ionization": ground_state_model_conversion}

def fill_in_ionization_electron_species(
self,
pypicongpu_by_picmi_species: dict[picmistandard.PICMI_Species, pypicongpu.species.Species],
ionization_model_conversion_by_species: dict[
str,
dict[
picmistandard.PICMI_Species,
dict[GroundStateIonizationModel, pypicongpu.species.constant.ionizationmodel.IonizationModel],
],
],
) -> None:
"""
add ionization models to pypicongpu species
in PICMI ioniaztion is defined as a list ionization models owned by the simulation, with each ionization model
storing its PICMI ion and PICMI ionization electron species.
In contrast in PyPIConGPU each ion PyPIConGPU species owns a list of ionization models, each storing its
PyPIConGPU ionization electron species.
This creates the problem that upon translation of the PICMI species to an PyPIConGPU species the PyPIConGPU
ionization electron species might not exist yet.
Therefore we leave the ionization electron unspecified upon species creation and fill it in from the PICMI
simulation ionization model list later.
(An because python uses pointers, this will be applied to the existing species objects passed in
pypicongpu_by_picmi_species)
"""

# groundstate ionization model
for species, ionization_model_conversion in ionization_model_conversion_by_species[
"ground_state_ionization"
].items():
for picmi_ionization_model, pypicongpu_ionization_model in ionization_model_conversion.items():
pypicongpu_ionization_electron_species = pypicongpu_by_picmi_species[
picmi_ionization_model.ionization_electron_species
]
pypicongpu_ionization_model.ionization_electron_species = pypicongpu_ionization_electron_species

def has_ground_state_ionization(self, species: Species) -> bool:
"""does at least one ground state ionization model list species as ion species?"""
for ionization_model in self.ground_state_ionization_model_list:
if species == ionization_model.ion_species:
return True
return False

def has_ionization(self, species: Species) -> bool:
"""does at least one ionization model list species as ion species?"""

# add additional groups of ionization models here
ionization_configured = self.has_ground_state_ionization(species)
return ionization_configured
29 changes: 29 additions & 0 deletions lib/python/picongpu/picmi/interaction/interactioninterface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
This file is part of PIConGPU.
Copyright 2024 PIConGPU contributors
Authors: Brian Edward Marre
License: GPLv3+
"""

from ... import pypicongpu

import picmistandard
import pydantic


class InteractionInterface(pydantic.BaseModel):
"""
interface for forward declaration
"""

def get_interaction_constants(
self, species: picmistandard.PICMI_Species
) -> list[pypicongpu.species.constant.Constant]:
"""get list of all constants required by interactions for the given species"""
raise NotImplementedError("abstract interface for forward declaration only!")

def fill_in_ionization_electron_species(
self, pypicongpu_by_picmi_species: dict[picmistandard.PICMI_Species, pypicongpu.species.Species]
):
"""add ionization electron species to pypicongpu species' ionization model"""
raise NotImplementedError("abstract interface for forward declaration only!")
10 changes: 7 additions & 3 deletions lib/python/picongpu/picmi/interaction/ionization/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from .ionizationmodel import IonizationModel
from . import ionizationcurrent
from .groundstateionizationmodel import GroundStateIonizationModel
from . import fieldionization
from . import electroniccollisionalequilibrium

__all__ = ["IonizationModel", "ionizationcurrent", "fieldionization", "electroniccollisionalequilibrium"]
__all__ = [
"IonizationModel",
"GroundStateIonizationModel",
"fieldionization",
"electroniccollisionalequilibrium",
]
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
License: GPLv3+
"""

from ..ionizationmodel import IonizationModel
from ..groundstateionizationmodel import GroundStateIonizationModel
from ..... import pypicongpu


class ThomasFermi(IonizationModel):
class ThomasFermi(GroundStateIonizationModel):
"""thomas fermi ionization model"""

MODEL_NAME: str = "ThomasFermi"

def get_as_pypicongpu(self) -> pypicongpu.species.constant.ionizationmodel.IonizationModel:
return pypicongpu.species.constant.ionizationmodel.ThomasFermi()
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

from .fieldionization import FieldIonization

from .....pypicongpu.species.constant.ionizationcurrent import None_
from .....pypicongpu.species.constant.ionizationmodel import ADKLinearPolarization, ADKCircularPolarization

from ..... import pypicongpu

import enum


Expand All @@ -22,3 +27,12 @@ class ADK(FieldIonization):

ADK_variant: ADKVariant
"""extension to the BSI model"""

def get_as_pypicongpu(self) -> pypicongpu.species.constant.ionizationmodel.IonizationModel:
if self.ADK_variant is ADKVariant.LinearPolarization:
return ADKLinearPolarization(ionization_current=None_)
if self.ADK_variant is ADKVariant.CircularPolarization:
return ADKCircularPolarization(ionization_current=None_)

# unknown/unsupported ADK variant
pypicongpu.util.unsupported(f"ADKVariant {self.ADK_variant}")
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

from .fieldionization import FieldIonization

from .....pypicongpu.species.constant.ionizationcurrent import None_
from .....pypicongpu.species.constant import ionizationmodel

from ..... import pypicongpu

import enum


Expand All @@ -22,5 +27,19 @@ class BSI(FieldIonization):

MODEL_NAME: str = "BSI"

BIS_extensions: list[BSIExtension]
BSI_extensions: list[BSIExtension]
"""extension to the BSI model"""

def get_as_pypicongpu(self) -> pypicongpu.species.constant.ionizationmodel.IonizationModel:
if self.BSI_extensions == []:
return ionizationmodel.BSI(ionization_current=None_)

if self.BSI_extensions == [BSIExtension.StarkShift]:
return ionizationmodel.BSIStarkShifted(ionization_current=None_)
if self.BSI_extensions == [BSIExtension.EffectiveZ]:
return ionizationmodel.BSIEffectiveZ(ionization_current=None_)

if len(self.BSI_extensions) > 1:
pypicongpu.util.unsupported("more than one BSI_extension")
else:
pypicongpu.util.unsupported(f"unknown BSI_extension {self.BSI_extensions[0]}")
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@
License: GPLv3+
"""

from .ionizationmodel import IonizationModel
from ..groundstateionizationmodel import GroundStateIonizationModel
from .ionizationcurrent import IonizationCurrent

import typing


class FieldIonization(IonizationModel):
class FieldIonization(GroundStateIonizationModel):
"""common interface of all field ionization models"""

ionization_current: typing.Optional[IonizationCurrent]
"""ionization current for energy conservation of field ionization"""

# + all IonizationModel interface requirements
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@

from .fieldionization import FieldIonization

from .....pypicongpu.species.constant.ionizationcurrent import None_
from .....pypicongpu.species.constant import ionizationmodel

from ..... import pypicongpu


class Keldysh(FieldIonization):
"""Barrier Suppression Ioniztion model"""

MODEL_NAME: str = "Keldysh"

def get_as_pypicongpu(self) -> pypicongpu.species.constant.ionizationmodel.IonizationModel:
return ionizationmodel.Keldysh(ionization_current=None_)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""
This file is part of PIConGPU.
Copyright 2024 PIConGPU contributors
Authors: Brian Edward Marre
License: GPLv3+
"""

from .ionizationmodel import IonizationModel

from .... import pypicongpu


class GroundStateIonizationModel(IonizationModel):
def get_constants(self) -> list[pypicongpu.species.constant.Constant]:
"""get all PyPIConGPU constants required by a ground state ionization model in PIConGPU"""
Z = self.ion_species.picongpu_element.get_atomic_number()
assert self.ion_species.charge_state <= Z, f"charge_state must be <= atomic number ({Z})"

element_properties_const = pypicongpu.species.constant.ElementProperties()
element_properties_const.element = self.ion_species.picongpu_element
return element_properties_const
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""

from ...species import Species
from .... import pypicongpu

import pydantic

Expand All @@ -21,7 +22,13 @@ class IonizationModel(pydantic.BaseModel):
"""ionization model"""

ion_species: Species
"""ion species to apply ionization model for"""
"""PICMI ion species to apply ionization model for"""

ionization_electron_species: Species
"""electron species of which to create macro particle upon ionization"""
"""PICMI electron species of which to create macro particle upon ionization"""

def get_constants(self) -> list[pypicongpu.species.constant.Constant]:
raise NotImplementedError("abstract base class only!")

def get_as_pypicongpu(self) -> pypicongpu.species.constant.ionizationmodel.IonizationModel:
raise NotImplementedError("abstract base class only!")
1 change: 1 addition & 0 deletions lib/python/picongpu/picmi/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ picmistandard >= 0.27.0
typeguard >= 4.2.1
sympy >= 1.9
pydantic >= 2.6.4
pdg >= 0.1.2
-r ../pypicongpu/requirements.txt
Loading

0 comments on commit 60817b9

Please sign in to comment.