diff --git a/src/cli/BeamExtract.py b/src/cli/BeamExtract.py new file mode 100755 index 0000000000..ab5051be54 --- /dev/null +++ b/src/cli/BeamExtract.py @@ -0,0 +1,287 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +# before you start: +#!conda install -c conda-forge -y mamba +#!mamba install -c conda-forge -y openpmd-api openpmd-viewer ipympl fast-histogram + +######################################################################################################################################## + +import json +import sys + +import numpy as np +import openpmd_api as io + +######################################################################################################################################## + +if len(sys.argv) == 1: + print("ABORTED: Please pass a run as command line argument.") + sys.exit(1) +Runs = sys.argv[1:] +print("Working on runs: ", Runs) + +######################################################################################################################################## +for Run in Runs: + + sim = '../' + Run + '/' + + input_series = io.Series(sim + "diags/openPMD/openpmd_%T.bp", io.Access.read_only) + input_series.backend + + #!rm -rf particle_extract.* + + output_series = io.Series(sim + "particle_extract_9000.bp", io.Access.create) + output_series.backend + + ###################################################################################################################################### + + # species record: filter + def filter_species(in_p, in_slice): + """ + example: filter by z position + """ + # prepare reading of records of the current slice + # note: you can read more than one record to use for filtering + pos_x = in_p["position"]["x"][in_slice] + pos_y = in_p["position"]["y"][in_slice] + pos_z = in_p["position"]["z"][in_slice] + + # trigger read operations + in_p.series_flush() + + # example here: simple position threshold filter + # assumption: unitSI is 1.0 and positionOffset are zero + filter_data = (pos_z > 16e-06) & (np.abs(pos_x) < 5.0e-6) & (np.abs(pos_y) < 5.0e-6) + + # return binary filter array for the current slice + return filter_data + + ###################################################################################################################################### + + k_it = 9000 # time step for beam extraction + + ###################################################################################################################################### + + # avoid running out-of-memory: maximum number of particles to copy at once + slice_size = 250_000_000 # 250 million particles at a time + + ###################################################################################################################################### + + # compress extracted datasets, unless they are chunked (most of them are) + dataset_config = { + 'adios2': { + 'dataset': { + } + } + } + dataset_config['adios2']['dataset'] = { + 'operators': [{ + 'type': 'blosc', + 'parameters': { + 'compressor': '1', + 'clevel': '1', + 'threshold': '2048', + 'nthreads': '6', + 'doshuffle': 'BLOSC_BITSHUFFLE' + } + }] + } + + # resizable data sets w/ compression seem to crash in write as of 0.14.5 + dataset_config_resizable = {} # dataset_config + dataset_config_resizable['resizable'] = True + + ###################################################################################################################################### + + # single iteration + in_it = input_series.iterations[k_it] + for _ in [k_it]: + + # OR all iterations: + #for k_it, in_it in input_series.iterations.items(): + print(f"Iteration: {k_it}") + out_it = output_series.iterations[k_it] + + # particle species + for k_p, in_p in in_it.particles.items(): + print(f" Particle species '{k_p}'") + out_p = out_it.particles[k_p] + + num_particles = in_p["momentum"]["x"].shape[0] + print(f" Number of particles: {num_particles}") + + N_pass = int(np.ceil(num_particles/slice_size)) + print(f" number of passes: {N_pass}") + + # bookkeeping in the global output arrays of the species + out_slice_start = 0 + out_slice_end = 0 + + # stepping through particle in slices + for slice_start in range(0, num_particles, slice_size): + slice_end = slice_start + slice_size + if slice_end > num_particles: + slice_end = num_particles + #print(' {:,} {:,}'.format(slice_start, slice_end)) + in_slice = np.s_[slice_start:slice_end] + + # species record: filter + accepted = filter_species(in_p, in_slice) + out_slice_end = out_slice_start + np.sum(accepted) + + if out_slice_end == out_slice_start: + continue + + # species records + for k_p_r, in_p_r in in_p.items(): + print(f" {k_p_r}") + + # species record components: data + for k_p_rc, in_p_rc in in_p_r.items(): + print(f" {k_p_rc} {in_p_rc.shape}->[{slice_start}:{slice_end}]") + + # copy data + if in_p_rc.empty: + out_p_r = out_p[k_p_r] + out_p_rc = out_p_r[k_p_rc] + if not out_p_rc.empty: + dataset = io.Dataset(in_p_rc.dtype, (0, )) + dataset.options = json.dumps(dataset_config) + out_p_rc.reset_dataset(dataset) + # out_p_rc.make_empty(dtype, 1) # done by reset_datatype w/ zero shape already + elif in_p_rc.constant: + # later, once we know the final shape + pass + else: + data = in_p_rc[in_slice] + input_series.flush() + + # write accepted particles back + out_slice = np.s_[out_slice_start:out_slice_end] + print(f" out_slice={out_slice}, {out_slice_start}") + + out_p_r = out_p[k_p_r] + out_p_rc = out_p_r[k_p_rc] + dataset = io.Dataset(in_p_rc.dtype, (out_slice_end,)) + dataset.options = json.dumps(dataset_config_resizable) + out_p_rc.reset_dataset(dataset) + out_p_rc[out_slice] = data[accepted] + output_series.flush() + + out_slice_start = out_slice_end + # next species record + + # filter results are empty? + if out_slice_start == 0: + print(" Filter results for this iteration and species are empty!") + for k_p_r, in_p_r in in_p.items(): + out_p_r = out_p[k_p_r] + for k_p_rc, in_p_rc in in_p_r.items(): + out_p_rc = out_p_r[k_p_rc] + + if not out_p_rc.empty: + print(f" {k_p_r} {k_p_rc}") + dataset = io.Dataset(in_p_rc.dtype, (0,)) + dataset.options = json.dumps(dataset_config) + out_p_rc.reset_dataset(dataset) + # out_p_rc.make_empty(dtype, 1) # done by reset_datatype w/ zero shape already + else: + # write constant record components with final shape + print(" Writing constant record components") + for k_p_r, in_p_r in in_p.items(): + out_p_r = out_p[k_p_r] + for k_p_rc, in_p_rc in in_p_r.items(): + out_p_rc = out_p_r[k_p_rc] + + if in_p_rc.constant: + print(f" {k_p_r} {k_p_rc} {in_p_rc.shape}->[{out_slice_end}]") + dataset = io.Dataset(in_p_rc.dtype, (out_slice_end,)) + dataset.options = json.dumps(dataset_config) + out_p_rc.reset_dataset(dataset) + out_p_rc.make_constant(in_p_rc.get_attribute("value")) + + output_series.flush() + # next particle species + # next iteration + + output_series.flush() + + ###################################################################################################################################### + + # series attributes + dt_s = input_series.attribute_dtypes + for a in input_series.attributes: + print(f"{a}") + + # meshesPath: if this attribute is missing, the file is interpreted as if it contains no mesh records! If the attribute is set, the group behind it must exist! + if a in ["meshesPath"]: + print(" - skipped") + continue + + output_series.set_attribute(a, input_series.get_attribute(a), dt_s[a]) + + # iteration attributes + # single iteration + in_it = input_series.iterations[k_it] + dt_it = in_it.attribute_dtypes + for _ in [k_it]: + + # OR all iterations: + #for k_it, in_it in input_series.iterations.items(): + print(k_it) + out_it = output_series.iterations[k_it] + for a in in_it.attributes: + print(f" {a}") + out_it.set_attribute(a, in_it.get_attribute(a), dt_it[a]) + + # particles group attributes + in_pa = in_it.particles + out_pa = out_it.particles + dt_pa = in_pa.attribute_dtypes + for a in in_pa.attributes: + print(f" {a}") + out_pa.set_attribute(a, in_pa.get_attribute(a), dt_pa[a]) + + # per species attributes + for k_p, in_p in in_it.particles.items(): + print(k_p) + out_p = out_it.particles[k_p] + dt_p = in_it.particles[k_p].attribute_dtypes + for a in in_p.attributes: + print(f" {a}") + out_p.set_attribute(a, in_p.get_attribute(a), dt_p[a]) + + # species record attributes + for k_p_r, in_p_r in in_p.items(): + print(k_p, k_p_r) + out_p_r = out_p[k_p_r] + dt_p_r = in_p_r.attribute_dtypes + for a in in_p_r.attributes: + print(f" {a}") + if a in ["shape", "value"]: + print(" - skipped") + continue + out_p_r.set_attribute(a, in_p_r.get_attribute(a), dt_p_r[a]) + + # species record component attributes + for k_p_rc, in_p_rc in in_p_r.items(): + print(f" {k_p_rc}") + out_p_rc = out_p_r[k_p_rc] + dt_p_rc = in_p_rc.attribute_dtypes + for a in in_p_rc.attributes: + print(f" {a}") + if a in ["shape", "value"]: + print(" - skipped") + continue + out_p_rc.set_attribute(a, in_p_rc.get_attribute(a), dt_p_rc[a]) + + output_series.flush() + + ###################################################################################################################################### + + del input_series + del output_series + + ###################################################################################################################################### + print('This job is finished!') diff --git a/src/cli/particle_extract.ipynb b/src/cli/particle_extract.ipynb new file mode 100644 index 0000000000..ef4bc7101a --- /dev/null +++ b/src/cli/particle_extract.ipynb @@ -0,0 +1,800 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a2fce232-c7da-4666-a634-db934934696d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import json\n", + "import openpmd_api as io\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb913a51-e436-44ab-ab9d-9a2a1e9860af", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "input_series = io.Series(\"/home/axel/src/openPMD/openPMD-example-datasets/example-3d/hdf5/data%T.h5\", io.Access.read_only)\n", + "input_series.backend" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fab061d9-675d-4fd9-ad97-87304e008a8b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "!rm -rf particle_extract.*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9320f003-5683-4527-b110-b684996e3e89", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "output_series = io.Series(\"particle_extract.bp\", io.Access.create)\n", + "output_series.backend" + ] + }, + { + "cell_type": "markdown", + "id": "d25d3dba-5478-4d10-aac3-f14054bfa0bd", + "metadata": { + "tags": [] + }, + "source": [ + "## Filter Particles\n", + "\n", + "Apply changes per simulation extraction here :)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d9397148-84df-48ff-a0b2-c4c310d647b0", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# species record: filter\n", + "def filter_species(in_p, in_slice):\n", + " \"\"\"\n", + " example: filter by z position\n", + " \"\"\"\n", + " # prepare reading of records of the current slice\n", + " # note: you can read more than one record to use for filtering\n", + " pos_x = in_p[\"position\"][\"x\"][in_slice]\n", + " pos_y = in_p[\"position\"][\"y\"][in_slice]\n", + " pos_z = in_p[\"position\"][\"z\"][in_slice]\n", + "\n", + " # trigger read operations\n", + " in_p.series_flush()\n", + " \n", + " # example here: simple position threshold filter\n", + " # assumption: unitSI is 1.0 and positionOffset are zero\n", + " filter_data = (pos_z > 3.5e-05) & (np.abs(pos_x) < 5.0e-6) & (np.abs(pos_y) < 5.0e-6)\n", + "\n", + " # return binary filter array for the current slice\n", + " return filter_data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "47a0ce96-ed0c-49e2-8ba2-bceafc38b950", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "k_it = 400 # time step for beam extraction" + ] + }, + { + "cell_type": "markdown", + "id": "13681260-2fa2-469c-889d-bf55cb07d04a", + "metadata": { + "tags": [] + }, + "source": [ + "## Copy Particles" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7dc86882-ec8a-4a2f-8bfc-e3dcd0f56b95", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# avoid running out-of-memory: maximum number of particles to copy at once\n", + "slice_size = 250_000_000 # 250 million particles at a time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb13cd66-2c50-431e-a4d7-bdb72e8bc462", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# compress extracted datasets, unless they are chunked (most of them are)\n", + "dataset_config = {\n", + " 'adios2': {\n", + " 'dataset': {\n", + " }\n", + " }\n", + "}\n", + "dataset_config['adios2']['dataset'] = {\n", + " 'operators': [{\n", + " 'type': 'blosc',\n", + " 'parameters': {\n", + " 'compressor': '1',\n", + " 'clevel': '1',\n", + " 'threshold': '2048',\n", + " 'nthreads': '6',\n", + " 'doshuffle': 'BLOSC_BITSHUFFLE'\n", + " }\n", + " }]\n", + "}\n", + "\n", + "# resizable data sets w/ compression seem to crash in write as of 0.14.5\n", + "dataset_config_resizable = {} # dataset_config\n", + "dataset_config_resizable['resizable'] = True" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f82f6170-c826-45e3-ae4c-321554613386", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iteration: 400\n", + " Particle species 'electrons'\n", + " Number of particles: 270625\n", + " number of passes: 1\n", + " charge\n", + " \u000b", + "Scalar [270625]->[0:270625]\n", + " mass\n", + " \u000b", + "Scalar [270625]->[0:270625]\n", + " momentum\n", + " x [270625]->[0:270625]\n", + " out_slice=slice(0, 15717, None), 0\n", + " y [270625]->[0:270625]\n", + " out_slice=slice(0, 15717, None), 0\n", + " z [270625]->[0:270625]\n", + " out_slice=slice(0, 15717, None), 0\n", + " position\n", + " x [270625]->[0:270625]\n", + " out_slice=slice(0, 15717, None), 0\n", + " y [270625]->[0:270625]\n", + " out_slice=slice(0, 15717, None), 0\n", + " z [270625]->[0:270625]\n", + " out_slice=slice(0, 15717, None), 0\n", + " positionOffset\n", + " x [270625]->[0:270625]\n", + " y [270625]->[0:270625]\n", + " z [270625]->[0:270625]\n", + " weighting\n", + " \u000b", + "Scalar [270625]->[0:270625]\n", + " out_slice=slice(0, 15717, None), 0\n", + " Writing constant record components\n", + " charge \u000b", + "Scalar [270625]->[15717]\n", + " mass \u000b", + "Scalar [270625]->[15717]\n", + " positionOffset x [270625]->[15717]\n", + " positionOffset y [270625]->[15717]\n", + " positionOffset z [270625]->[15717]\n" + ] + } + ], + "source": [ + "# [donotremove]\n", + "\n", + "# single iteration\n", + "in_it = input_series.iterations[k_it]\n", + "for _ in [k_it]:\n", + "\n", + "# OR all iterations:\n", + "#for k_it, in_it in input_series.iterations.items():\n", + " print(f\"Iteration: {k_it}\")\n", + " out_it = output_series.iterations[k_it]\n", + "\n", + " # particle species\n", + " for k_p, in_p in in_it.particles.items():\n", + " print(f\" Particle species '{k_p}'\")\n", + " out_p = out_it.particles[k_p]\n", + "\n", + " num_particles = in_p[\"momentum\"][\"x\"].shape[0]\n", + " print(f\" Number of particles: {num_particles}\")\n", + "\n", + " N_pass = int(np.ceil(num_particles/slice_size))\n", + " print(f\" number of passes: {N_pass}\")\n", + " \n", + " # bookkeeping in the global output arrays of the species\n", + " out_slice_start = 0\n", + " out_slice_end = 0\n", + "\n", + " # stepping through particle in slices\n", + " for slice_start in range(0, num_particles, slice_size):\n", + " slice_end = slice_start + slice_size\n", + " if slice_end > num_particles:\n", + " slice_end = num_particles\n", + " #print(' {:,} {:,}'.format(slice_start, slice_end))\n", + " in_slice = np.s_[slice_start:slice_end]\n", + " \n", + " # species record: filter\n", + " accepted = filter_species(in_p, in_slice)\n", + " out_slice_end = out_slice_start + np.sum(accepted)\n", + "\n", + " if out_slice_end == out_slice_start:\n", + " continue\n", + " \n", + " # species records\n", + " for k_p_r, in_p_r in in_p.items():\n", + " print(f\" {k_p_r}\")\n", + " \n", + " # species record components: data\n", + " for k_p_rc, in_p_rc in in_p_r.items():\n", + " print(f\" {k_p_rc} {in_p_rc.shape}->[{slice_start}:{slice_end}]\")\n", + "\n", + " # copy data\n", + " if in_p_rc.empty:\n", + " out_p_r = out_p[k_p_r]\n", + " out_p_rc = out_p_r[k_p_rc]\n", + " if not out_p_rc.empty:\n", + " dataset = io.Dataset(in_p_rc.dtype, (0, ))\n", + " dataset.options = json.dumps(dataset_config)\n", + " out_p_rc.reset_dataset(dataset)\n", + " # out_p_rc.make_empty(dtype, 1) # done by reset_datatype w/ zero shape already\n", + " elif in_p_rc.constant:\n", + " # later, once we know the final shape\n", + " pass\n", + " else:\n", + " data = in_p_rc[in_slice]\n", + " input_series.flush()\n", + "\n", + " # write accepted particles back\n", + " out_slice = np.s_[out_slice_start:out_slice_end]\n", + " print(f\" out_slice={out_slice}, {out_slice_start}\")\n", + "\n", + " out_p_r = out_p[k_p_r]\n", + " out_p_rc = out_p_r[k_p_rc]\n", + " dataset = io.Dataset(in_p_rc.dtype, (out_slice_end,))\n", + " dataset.options = json.dumps(dataset_config_resizable)\n", + " out_p_rc.reset_dataset(dataset)\n", + " out_p_rc[out_slice] = data[accepted]\n", + " output_series.flush()\n", + "\n", + " out_slice_start = out_slice_end\n", + " # next species record\n", + " \n", + " # filter results are empty?\n", + " if out_slice_start == 0:\n", + " print(\" Filter results for this iteration and species are empty!\")\n", + " for k_p_r, in_p_r in in_p.items():\n", + " out_p_r = out_p[k_p_r]\n", + " for k_p_rc, in_p_rc in in_p_r.items():\n", + " out_p_rc = out_p_r[k_p_rc]\n", + "\n", + " if not out_p_rc.empty:\n", + " print(f\" {k_p_r} {k_p_rc}\")\n", + " dataset = io.Dataset(in_p_rc.dtype, (0,))\n", + " dataset.options = json.dumps(dataset_config)\n", + " out_p_rc.reset_dataset(dataset)\n", + " # out_p_rc.make_empty(dtype, 1) # done by reset_datatype w/ zero shape already\n", + " else:\n", + " # write constant record components with final shape\n", + " print(\" Writing constant record components\")\n", + " for k_p_r, in_p_r in in_p.items():\n", + " out_p_r = out_p[k_p_r]\n", + " for k_p_rc, in_p_rc in in_p_r.items():\n", + " out_p_rc = out_p_r[k_p_rc]\n", + "\n", + " if in_p_rc.constant:\n", + " print(f\" {k_p_r} {k_p_rc} {in_p_rc.shape}->[{out_slice_end}]\")\n", + " dataset = io.Dataset(in_p_rc.dtype, (out_slice_end,))\n", + " dataset.options = json.dumps(dataset_config)\n", + " out_p_rc.reset_dataset(dataset)\n", + " out_p_rc.make_constant(in_p_rc.get_attribute(\"value\"))\n", + "\n", + " output_series.flush()\n", + " # next particle species\n", + " # next iteration\n", + "\n", + "output_series.flush()" + ] + }, + { + "cell_type": "markdown", + "id": "8a869600-1b00-4dcb-a105-bd62bbfc9487", + "metadata": { + "tags": [] + }, + "source": [ + "## Copy Attributes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "998d114f-47dc-48cd-a407-e7272a28b5e4", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "basePath\n", + "date\n", + "iterationEncoding\n", + "iterationFormat\n", + "meshesPath\n", + " - skipped\n", + "openPMD\n", + "openPMDextension\n", + "particlesPath\n", + "software\n", + "softwareVersion\n", + "400\n", + " dt\n", + " time\n", + " timeUnitSI\n", + "electrons\n", + " currentDeposition\n", + " particleInterpolation\n", + " particlePush\n", + " particleShape\n", + " particleSmoothing\n", + "electrons charge\n", + " macroWeighted\n", + " shape\n", + " - skipped\n", + " timeOffset\n", + " unitDimension\n", + " unitSI\n", + " value\n", + " - skipped\n", + " weightingPower\n", + " \u000b", + "Scalar\n", + " macroWeighted\n", + " shape\n", + " - skipped\n", + " timeOffset\n", + " unitDimension\n", + " unitSI\n", + " value\n", + " - skipped\n", + " weightingPower\n", + "electrons mass\n", + " macroWeighted\n", + " shape\n", + " - skipped\n", + " timeOffset\n", + " unitDimension\n", + " unitSI\n", + " value\n", + " - skipped\n", + " weightingPower\n", + " \u000b", + "Scalar\n", + " macroWeighted\n", + " shape\n", + " - skipped\n", + " timeOffset\n", + " unitDimension\n", + " unitSI\n", + " value\n", + " - skipped\n", + " weightingPower\n", + "electrons momentum\n", + " macroWeighted\n", + " timeOffset\n", + " unitDimension\n", + " weightingPower\n", + " x\n", + " unitSI\n", + " y\n", + " unitSI\n", + " z\n", + " unitSI\n", + "electrons position\n", + " macroWeighted\n", + " timeOffset\n", + " unitDimension\n", + " weightingPower\n", + " x\n", + " unitSI\n", + " y\n", + " unitSI\n", + " z\n", + " unitSI\n", + "electrons positionOffset\n", + " macroWeighted\n", + " timeOffset\n", + " unitDimension\n", + " weightingPower\n", + " x\n", + " shape\n", + " - skipped\n", + " unitSI\n", + " value\n", + " - skipped\n", + " y\n", + " shape\n", + " - skipped\n", + " unitSI\n", + " value\n", + " - skipped\n", + " z\n", + " shape\n", + " - skipped\n", + " unitSI\n", + " value\n", + " - skipped\n", + "electrons weighting\n", + " macroWeighted\n", + " timeOffset\n", + " unitDimension\n", + " unitSI\n", + " weightingPower\n", + " \u000b", + "Scalar\n", + " macroWeighted\n", + " timeOffset\n", + " unitDimension\n", + " unitSI\n", + " weightingPower\n" + ] + } + ], + "source": [ + "# [donotremove]\n", + "\n", + "# series attributes\n", + "dt_s = input_series.attribute_dtypes\n", + "for a in input_series.attributes:\n", + " print(f\"{a}\")\n", + "\n", + " # meshesPath: if this attribute is missing, the file is interpreted as if it contains no mesh records! If the attribute is set, the group behind it must exist!\n", + " if a in [\"meshesPath\"]:\n", + " print(\" - skipped\")\n", + " continue\n", + " \n", + " output_series.set_attribute(a, input_series.get_attribute(a), dt_s[a])\n", + "\n", + "# iteration attributes\n", + "# single iteration\n", + "in_it = input_series.iterations[k_it]\n", + "dt_it = in_it.attribute_dtypes\n", + "for _ in [k_it]:\n", + "\n", + "# OR all iterations:\n", + "#for k_it, in_it in input_series.iterations.items():\n", + " print(k_it)\n", + " out_it = output_series.iterations[k_it]\n", + " for a in in_it.attributes:\n", + " print(f\" {a}\")\n", + " out_it.set_attribute(a, in_it.get_attribute(a), dt_it[a])\n", + "\n", + " # particles group attributes\n", + " in_pa = in_it.particles\n", + " out_pa = out_it.particles\n", + " dt_pa = in_pa.attribute_dtypes\n", + " for a in in_pa.attributes:\n", + " print(f\" {a}\")\n", + " out_pa.set_attribute(a, in_pa.get_attribute(a), dt_pa[a])\n", + "\n", + " # per species attributes\n", + " for k_p, in_p in in_it.particles.items():\n", + " print(k_p)\n", + " out_p = out_it.particles[k_p]\n", + " dt_p = in_it.particles[k_p].attribute_dtypes\n", + " for a in in_p.attributes:\n", + " print(f\" {a}\")\n", + " out_p.set_attribute(a, in_p.get_attribute(a), dt_p[a])\n", + " \n", + " # species record attributes\n", + " for k_p_r, in_p_r in in_p.items():\n", + " print(k_p, k_p_r)\n", + " out_p_r = out_p[k_p_r]\n", + " dt_p_r = in_p_r.attribute_dtypes\n", + " for a in in_p_r.attributes:\n", + " print(f\" {a}\")\n", + " if a in [\"shape\", \"value\"]:\n", + " print(\" - skipped\")\n", + " continue\n", + " out_p_r.set_attribute(a, in_p_r.get_attribute(a), dt_p_r[a])\n", + " \n", + " # species record component attributes\n", + " for k_p_rc, in_p_rc in in_p_r.items():\n", + " print(f\" {k_p_rc}\")\n", + " out_p_rc = out_p_r[k_p_rc]\n", + " dt_p_rc = in_p_rc.attribute_dtypes\n", + " for a in in_p_rc.attributes:\n", + " print(f\" {a}\")\n", + " if a in [\"shape\", \"value\"]:\n", + " print(\" - skipped\")\n", + " continue\n", + " out_p_rc.set_attribute(a, in_p_rc.get_attribute(a), dt_p_rc[a])\n", + "\n", + "output_series.flush()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d46de8d-25f1-4150-9a52-e69a83054860", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "openPMD series: data%T\n", + "openPMD standard: 1.1.0\n", + "openPMD extensions: 1\n", + "\n", + "data author: unknown\n", + "data created: 2018-02-06 09:40:21 -0800\n", + "data backend: HDF5\n", + "generating machine: unknown\n", + "generating software: warp (version: 4)\n", + "generating software dependencies: unknown\n", + "\n", + "number of iterations: 5 (fileBased)\n", + " all iterations: 100 200 300 400 500 \n", + "\n", + "number of meshes: 2\n", + " all meshes:\n", + " E\n", + " rho\n", + "\n", + "number of particle species: 1\n", + " all particle species:\n", + " electrons\n", + "\n" + ] + } + ], + "source": [ + "# [donotremove]\n", + "io.list_series(input_series, longer=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5002b0d1-c480-4625-a63d-009878e43794", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "openPMD series: particle_extract\n", + "openPMD standard: 1.1.0\n", + "openPMD extensions: 1\n", + "\n", + "data author: unknown\n", + "data created: 2018-02-06 09:40:21 -0800\n", + "data backend: ADIOS2\n", + "generating machine: unknown\n", + "generating software: warp (version: 4)\n", + "generating software dependencies: unknown\n", + "\n", + "number of iterations: 1 (groupBased)\n", + " all iterations: 400 \n", + "\n", + "number of meshes: 0\n", + "\n", + "number of particle species: 1\n", + " all particle species:\n", + " electrons\n", + "\n" + ] + } + ], + "source": [ + "# [donotremove]\n", + "io.list_series(output_series, longer=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af2f6e29-0b5a-406e-854a-f7ff1d77d9f6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "del input_series\n", + "del output_series" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1fd36fe4-bba0-4e88-9c56-0680b3ee610b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "File info:\n", + " of variables: 7\n", + " of attributes: 66\n", + "\n", + " double /data/400/particles/electrons/momentum/x {15717}\n", + " double /data/400/particles/electrons/momentum/y {15717}\n", + " double /data/400/particles/electrons/momentum/z {15717}\n", + " double /data/400/particles/electrons/position/x {15717}\n", + " double /data/400/particles/electrons/position/y {15717}\n", + " double /data/400/particles/electrons/position/z {15717}\n", + " double /data/400/particles/electrons/weighting {15717}\n" + ] + } + ], + "source": [ + "# [donotremove]\n", + "!bpls -v particle_extract.bp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1a9ca83-807e-419c-90a2-87b7cdadf9fe", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " string /basePath attr = \"/data/%T/\"\n", + " uint8_t /data/400/closed attr = 1\n", + " double /data/400/dt attr = 3.28471e-16\n", + " uint32_t /data/400/particles/electrons/charge/macroWeighted attr = 0\n", + " uint64_t /data/400/particles/electrons/charge/shape attr = 15717\n", + " double /data/400/particles/electrons/charge/timeOffset attr = 0\n", + " double /data/400/particles/electrons/charge/unitDimension attr = {0, 0, 1, 1, 0, 0, 0}\n", + " double /data/400/particles/electrons/charge/unitSI attr = 1\n", + " double /data/400/particles/electrons/charge/value attr = -1.60218e-19\n", + " double /data/400/particles/electrons/charge/weightingPower attr = 1\n", + " string /data/400/particles/electrons/currentDeposition attr = \"Esirkepov\"\n", + " uint32_t /data/400/particles/electrons/mass/macroWeighted attr = 0\n", + " uint64_t /data/400/particles/electrons/mass/shape attr = 15717\n", + " double /data/400/particles/electrons/mass/timeOffset attr = 0\n", + " double /data/400/particles/electrons/mass/unitDimension attr = {1, 0, 0, 0, 0, 0, 0}\n", + " double /data/400/particles/electrons/mass/unitSI attr = 1\n", + " double /data/400/particles/electrons/mass/value attr = 9.10938e-31\n", + " double /data/400/particles/electrons/mass/weightingPower attr = 1\n", + " uint32_t /data/400/particles/electrons/momentum/macroWeighted attr = 0\n", + " double /data/400/particles/electrons/momentum/timeOffset attr = 0\n", + " double /data/400/particles/electrons/momentum/unitDimension attr = {1, 1, -1, 0, 0, 0, 0}\n", + " double /data/400/particles/electrons/momentum/weightingPower attr = 1\n", + " double /data/400/particles/electrons/momentum/x {15717} = 0 / 0\n", + " double /data/400/particles/electrons/momentum/x/unitSI attr = 1\n", + " double /data/400/particles/electrons/momentum/y {15717} = 0 / 0\n", + " double /data/400/particles/electrons/momentum/y/unitSI attr = 1\n", + " double /data/400/particles/electrons/momentum/z {15717} = 0 / 0\n", + " double /data/400/particles/electrons/momentum/z/unitSI attr = 1\n", + " string /data/400/particles/electrons/particleInterpolation attr = \"momentumConserving\"\n", + " string /data/400/particles/electrons/particlePush attr = \"Vay\"\n", + " double /data/400/particles/electrons/particleShape attr = 3\n", + " string /data/400/particles/electrons/particleSmoothing attr = \"none\"\n", + " uint32_t /data/400/particles/electrons/position/macroWeighted attr = 0\n", + " double /data/400/particles/electrons/position/timeOffset attr = 0\n", + " double /data/400/particles/electrons/position/unitDimension attr = {1, 0, 0, 0, 0, 0, 0}\n", + " double /data/400/particles/electrons/position/weightingPower attr = 0\n", + " double /data/400/particles/electrons/position/x {15717} = 0 / 0\n", + " double /data/400/particles/electrons/position/x/unitSI attr = 1\n", + " double /data/400/particles/electrons/position/y {15717} = 0 / 0\n", + " double /data/400/particles/electrons/position/y/unitSI attr = 1\n", + " double /data/400/particles/electrons/position/z {15717} = 0 / 0\n", + " double /data/400/particles/electrons/position/z/unitSI attr = 1\n", + " uint32_t /data/400/particles/electrons/positionOffset/macroWeighted attr = 0\n", + " double /data/400/particles/electrons/positionOffset/timeOffset attr = 0\n", + " double /data/400/particles/electrons/positionOffset/unitDimension attr = {1, 0, 0, 0, 0, 0, 0}\n", + " double /data/400/particles/electrons/positionOffset/weightingPower attr = 0\n", + " uint64_t /data/400/particles/electrons/positionOffset/x/shape attr = 15717\n", + " double /data/400/particles/electrons/positionOffset/x/unitSI attr = 1\n", + " double /data/400/particles/electrons/positionOffset/x/value attr = 0\n", + " uint64_t /data/400/particles/electrons/positionOffset/y/shape attr = 15717\n", + " double /data/400/particles/electrons/positionOffset/y/unitSI attr = 1\n", + " double /data/400/particles/electrons/positionOffset/y/value attr = 0\n", + " uint64_t /data/400/particles/electrons/positionOffset/z/shape attr = 15717\n", + " double /data/400/particles/electrons/positionOffset/z/unitSI attr = 1\n", + " double /data/400/particles/electrons/positionOffset/z/value attr = 0\n", + " double /data/400/particles/electrons/weighting {15717} = 0 / 0\n", + " uint32_t /data/400/particles/electrons/weighting/macroWeighted attr = 1\n", + " double /data/400/particles/electrons/weighting/timeOffset attr = 0\n", + " double /data/400/particles/electrons/weighting/unitDimension attr = {0, 0, 0, 0, 0, 0, 0}\n", + " double /data/400/particles/electrons/weighting/unitSI attr = 1\n", + " double /data/400/particles/electrons/weighting/weightingPower attr = 1\n", + " double /data/400/time attr = 1.31388e-13\n", + " double /data/400/timeUnitSI attr = 1\n", + " string /date attr = \"2018-02-06 09:40:21 -0800\"\n", + " string /iterationEncoding attr = \"fileBased\"\n", + " string /iterationFormat attr = \"data%T.h5\"\n", + " string /openPMD attr = \"1.1.0\"\n", + " uint32_t /openPMDextension attr = 1\n", + " string /particlesPath attr = \"particles/\"\n", + " string /software attr = \"warp\"\n", + " string /softwareVersion attr = \"4\"\n", + " uint64_t __openPMD_internal/openPMD2_adios2_schema attr = 0\n", + " uint8_t __openPMD_internal/useSteps attr = 0\n" + ] + } + ], + "source": [ + "# [donotremove]\n", + "!bpls -a -l particle_extract.bp" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}