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

Fix #6187: new 3d crystal plot #6215

Merged
merged 22 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions sirepo/package_data/static/html/silas-thermal-transport.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@
<div class="col-md-6 col-xl-4" data-ng-if="crystal.simState.isStateCompleted()">
<div data-report-panel="parameter" data-model-name="tempProfileAnimation"></div>
</div>
<div class="col-md-6 col-xl-4" data-ng-if="crystal.hasCrystal3d()">
<div data-report-panel="crystal3d" data-model-name="crystal3dAnimation"></div>
</div>
</div>
</div>
24 changes: 6 additions & 18 deletions sirepo/package_data/static/js/silas.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ var srdbg = SIREPO.srdbg;

SIREPO.app.config(function() {
SIREPO.INITIAL_INTENSITY_REPORT_TITLE = 'Initial Laser Pulse';
SIREPO.SINGLE_FRAME_ANIMATION = [
'plotAnimation',
'plot2Animation',
'crystal3dAnimation',
];
SIREPO.SINGLE_FRAME_ANIMATION = [];
SIREPO.appFieldEditors += `
<div data-ng-switch-when="FloatArray" class="col-sm-7">
<div data-num-array="" data-model="model" data-field-name="field" data-field="model[field]" data-info="info" data-num-type="Float"></div>
Expand Down Expand Up @@ -50,7 +46,7 @@ SIREPO.app.factory('silasService', function(appState) {
const self = {};

self.computeModel = (analysisModel) => {
if (['crystalAnimation', 'crystal3dAnimation', 'plotAnimation', 'plot2Animation', 'tempHeatMapAnimation', 'tempProfileAnimation'].indexOf(analysisModel) >= 0) {
if (['crystalAnimation', 'crystal3dAnimation', 'tempHeatMapAnimation', 'tempProfileAnimation'].indexOf(analysisModel) >= 0) {
return 'crystalAnimation';
}
if (['laserPulseAnimation', 'laserPulse2Animation'].includes(analysisModel)) {
Expand Down Expand Up @@ -189,14 +185,6 @@ SIREPO.app.controller('CrystalController', function (appState, frameCache, persi

self.simState = persistentSimulation.initSimulationState(self);
self.simState.errorMessage = () => errorMessage;

appState.whenModelsLoaded($scope, () => {
$scope.$on('plotAnimation.summaryData', function (e, data) {
if (data.crystalLength && data.crystalLength != silasService.getThermalCrystal().length) {
frameCache.setFrameCount(0);
}
});
});
});

SIREPO.app.directive('appFooter', function(appState, silasService) {
Expand Down Expand Up @@ -677,11 +665,12 @@ SIREPO.app.directive('crystal3d', function(appState, plotting, silasService, plo
let len = [];
let indices = [];
let verts = data.vertices;
const c = appState.applicationState().thermalTransportCrystal.crystal;
let size = $scope.boundAxis == 'Z'
? silasService.getThermalCrystal().length
: appState.applicationState().thermalTransportCrystal.crystal.inversion_mesh_extent * 2;
? c.length
: c.inversion_mesh_extent * 2 * 100;
let axisIdx = $scope.axes.indexOf($scope.boundAxis);
$scope.bound = (size + 0.01) * ($scope.sliderValue - 50) / 100;
$scope.bound = (size + 0.01) * $scope.sliderValue / 100 - size / 2;
for (let i = 0; i < data.indices.length; i += 3) {
if (checkBounds(i, axisIdx)) {
indices.push(data.indices[i], data.indices[i + 1], data.indices[i + 2]);
Expand Down Expand Up @@ -732,7 +721,6 @@ SIREPO.app.directive('crystal3d', function(appState, plotting, silasService, plo
camera.setFocalPoint(0, 0, 0);
camera.setViewUp(0, -1, 0);
renderer.resetCamera();
camera.zoom(1.3);
orientationMarker.updateMarkerOrientation();
}
fsRenderer.getRenderWindow().render();
Expand Down
15 changes: 3 additions & 12 deletions sirepo/package_data/static/json/silas-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
"x": ["Horizontal Value to Plot", "ValueList", "x"],
"y1": ["Vertical Value to Plot", "ValueList", "y"],
"histogramBins": ["Histogram Bins", "Integer", 200],
"colorMap": ["Color Map", "ColorMap", "afmhot"]
"colorMap": ["Color Map", "ColorMap", "viridis"]
},
"crystal3dAnimation": {},
"laserPulse": {
Expand Down Expand Up @@ -192,8 +192,6 @@
"_super": ["_", "model", "beamElement"],
"title": ["Element Name", "String", "Mirror"]
},
"plotAnimation": {},
"plot2Animation": {},
"simulation": {
"distanceFromSource": ["", "Float", 0.0 , "", 0.0]
},
Expand Down Expand Up @@ -297,7 +295,8 @@
},
"crystal3dAnimation": {
"title": "Crystal 3D Mesh",
"advanced": []
"advanced": [],
"canFullScreen": false
},
"mirror2": {
"title": "Two Mirrors",
Expand Down Expand Up @@ -364,14 +363,6 @@
"focalLength"
]
},
"plotAnimation": {
"title": "Radial Temperature Profile",
"advanced": []
},
"plot2Animation": {
"title": "Longitudinal Temperature Profile",
"advanced": []
},
"n0n2Plot": {
"title": "",
"advanced": []
Expand Down
76 changes: 38 additions & 38 deletions sirepo/package_data/template/silas/crystal.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,31 @@ crystal = Crystal(params=PKDict({{crystalParams}}))
sim_type = "{{ thermalCrystal.calc_type }}"

def thermo_optic_sim():
thermo = ThermoOptic(crystal, {{thermalCrystal.mesh_density}})
def _solve():
if sim_type == "analytical":
return thermo.{{ pump_pulse_profile }}_solution()

# Initialize a simulator with a crystal object set
# Set evaluation points & boundary conditions
elif sim_type == "fenics":
thermo.set_boundary(2*(crystal.radius*100.)**2./40.)
thermo.set_load('{{ pump_pulse_profile }}')
r = crystal.params.pop_inversion_pump_rep_rate
if r <= 1:
return thermo.slow_solution('{{ pump_pulse_profile }}')
elif r >= 100:
return thermo.solve_steady()
else:
raise AssertionError(f"Invalid rep rate for simulated solve heat_load={'{{ pump_pulse_profile }}'}")

thermo = ThermoOptic(crystal, {{ thermalCrystal.mesh_density }})

# prep for 2d solve
thermo.set_points((
{{thermalTransportSettings_grid_points_r}},
{{thermalTransportSettings_grid_points_w}},
{{thermalTransportSettings_grid_points_z}},
), {{thermalTransportSettings_edge_fraction}})
thermo.set_boundary(2*(crystal.radius*100.)**2./40.)

if sim_type == "analytical":
Ts = thermo.{{ pump_pulse_profile }}_solution()
))
res_2d = _solve()

elif sim_type == "fenics":
thermo.set_load('{{ pump_pulse_profile }}')
r = crystal.params.pop_inversion_pump_rep_rate
if r <= 1:
Ts = thermo.slow_solution('{{ pump_pulse_profile }}')
elif r >= 100:
Ts = thermo.solve_steady()
else:
raise AssertionError(f"Invalid rep rate for simulated solve heat_load={'{{ pump_pulse_profile }}'}")

nT, n0Fit, n2Fit = thermo.compute_indices(Ts)
# Positions of each evaluation point & sets of the unique values
ptzs = thermo.eval_pts[:, 2]
ptrs = (thermo.eval_pts[:, 0] ** 2 + thermo.eval_pts[:, 1] ** 2) ** 0.5
zs = unique(ptzs)
Expand All @@ -44,37 +43,38 @@ def thermo_optic_sim():
zface = zs.min() if crystal.params.pop_inversion_pump_type != "right" else zs.max()

# Radial values reflected across axis & meshgrid with longitudinal values
rrs = array((-rs[::-1]).tolist() + rs[1:].tolist())
RZ, ZR = meshgrid(rrs, zs)
temp_profile = PKDict(
radial=[rs, Ts[ptzs==zface]],
longitudinal=[zs, Ts[ptrs==rcenter]]
radial=[rs, res_2d[ptzs==zface]],
longitudinal=[zs, res_2d[ptrs==rcenter]]
)
pTs = Ts.reshape((len(rs), len(zs)), order='F')
pTs = res_2d.reshape((len(rs), len(zs)), order='F')
pTs = array((pTs[::-1]).tolist()+pTs[1:].tolist())
heat_map = pTs

# prep for 3d solve
mesh = thermo.mesh
inds = []
for item in dolfin.cpp.mesh.facets(mesh):
inds.append(item.entities(0).tolist())
vertices = mesh.coordinates()
thermo.eval_pts = vertices
res_3d = _solve()
return PKDict(
thermo=thermo,
heat_map=heat_map,
heat_map=pTs,
temp_profile=temp_profile,
nT=nT,
n0Fit=n0Fit,
n2Fit=n2Fit,
intensity=res_3d,
vertices=vertices,
indices=numpy.array(inds),
)


res = thermo_optic_sim()

# for 3D plots, get the facets, and build an array
# containing the indices of their coordinates
inds = []
for item in dolfin.cpp.mesh.facets(res.thermo.mesh):
inds.append(item.entities(0).tolist())

# we will provide these indices to plotly so it can draw proper surfaces
inds = numpy.array(inds)
numpy.save("indices.npy", inds)
numpy.save("vertices.npy", res.thermo.mesh.coordinates())
numpy.save("indices.npy", res.indices)
numpy.save("intensity.npy", res.intensity)
numpy.save("vertices.npy", res.vertices)
template_common.write_dict_to_h5(
res.temp_profile,
"tempProfile.h5"
Expand Down
3 changes: 0 additions & 3 deletions sirepo/package_data/template/silas/examples/bella.json
Original file line number Diff line number Diff line change
Expand Up @@ -612,11 +612,8 @@
"reportType": "3d",
"watchpointPlot": "total_intensity"
},
"plot2Animation": {},
"plotAnimation": {},
"simulation": {
"distanceFromSource": 0,
"documentationUrl": "",
"folder": "/Examples",
"name": "100TW amplifier with 3 crystals"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,12 +318,9 @@
"sigy_waist": 0.003056,
"wfs": ""
},
"plot2Animation": {},
"plotAnimation": {},
"simulation": {
"distanceFromSource": 0,
"folder": "/Examples",
"isExample": true,
"name": "Multiple Passes Through Single Crystal"
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,9 @@
"sigy_waist": 0.001,
"wfs": ""
},
"plot2Animation": {},
"plotAnimation": {},
"simulation": {
"distanceFromSource": 0,
"folder": "/Examples",
"isExample": true,
"name": "Single Crystal"
},
"watchpointReport3": {
Expand Down
2 changes: 0 additions & 2 deletions sirepo/sim_data/silas.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ def _compute_model(cls, analysis_model, *args, **kwargs):
"crystal3dAnimation",
"tempProfileAnimation",
"tempHeatMapAnimation",
"plotAnimation",
"plot2Animation",
):
return "crystalAnimation"
if "beamlineAnimation" in analysis_model:
Expand Down
59 changes: 1 addition & 58 deletions sirepo/template/silas.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

_SIM_DATA, SIM_TYPE, SCHEMA = sirepo.sim_data.template_globals()

_CRYSTAL_CSV_FILE = "crystal.csv"
_TEMP_PROFILE_FILE = "tempProfile.h5"
_TEMP_HEATMAP_FILE = "tempHeatMap.h5"
_RESULTS_FILE = "results{}.h5"
Expand Down Expand Up @@ -309,38 +308,6 @@ def _crystal_animation_percent_complete(run_dir, res, data):
return res


def _crystal_plot(frame_args):
x = None
plots = []
with open(str(frame_args.run_dir.join(_CRYSTAL_CSV_FILE))) as f:
for r in csv.reader(f):
if x is None and r[0] == x_column:
r.pop(0)
r.pop(0)
x = [float(v) * scale for v in r]
elif r[0] == y_column:
r.pop(0)
t = r.pop(0)
plots.append(
PKDict(
points=[float(v) for v in r],
label="{:.1f} sec".format(float(t)),
)
)
return PKDict(
title="",
x_range=[min(x), max(x)],
y_label="Temperature [°C]",
x_label=x_heading,
x_points=x,
plots=plots,
y_range=template_common.compute_plot_color_and_range(plots),
summaryData=PKDict(
crystalLength=_get_crystal(frame_args.sim_in).length,
),
)


def _generate_beamline_elements(data):
def _callback(state, element, dz):
if dz:
Expand Down Expand Up @@ -425,7 +392,7 @@ def _generate_parameters_file(data):

res, v = template_common.generate_parameters_file(data)
if data.report == "crystalAnimation":
c = _get_crystal(data)
c = data.models.thermalTransportCrystal.crystal
if c.pump_rep_rate <= 1:
c.calc_type = "fenics"
v.crystalParams = PKDict(
Expand All @@ -445,7 +412,6 @@ def _generate_parameters_file(data):
)
v.pump_pulse_profile = c.pump_pulse_profile
v.crystalLength = c.length
v.crystalCSV = _CRYSTAL_CSV_FILE
v.thermalCrystal = c
return res + template_common.render_jinja(SIM_TYPE, v, "crystal.py")
if data.report in _SIM_DATA.SOURCE_REPORTS:
Expand All @@ -461,10 +427,6 @@ def _generate_parameters_file(data):
return res + template_common.render_jinja(SIM_TYPE, v)


def _get_crystal(data):
return data.models.thermalTransportCrystal.crystal


def _initial_intensity_percent_complete(run_dir, res, data, model_names):
res.outputInfo = []
if run_dir.join(_RESULTS_FILE.format(0)).exists():
Expand Down Expand Up @@ -614,25 +576,6 @@ def gen(self):
raise AssertionError("Report is unavailable")


def _laser_pulse_report(value_index, filename, title, label):
values = numpy.load(filename)
return template_common.parameter_plot(
values[0].tolist(),
[
PKDict(
points=values[value_index].tolist(),
label=label,
),
],
PKDict(),
PKDict(
title=title,
y_label="",
x_label="s [m]",
),
)


def _parse_silas_log(run_dir):
res = ""
path = run_dir.join(template_common.RUN_LOG)
Expand Down