Added methodology page

This commit is contained in:
2025-04-16 18:04:34 +01:00
parent 4e340ef306
commit 86b4099c57
16 changed files with 782 additions and 51 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -30,6 +30,7 @@
}, },
"dependencies": { "dependencies": {
"@tailwindcss/forms": "^0.5.10", "@tailwindcss/forms": "^0.5.10",
"katex": "^0.16.22",
"lucide-svelte": "^0.471.0" "lucide-svelte": "^0.471.0"
}, },
"private": true "private": true

View File

@@ -0,0 +1,49 @@
<script lang="ts">
import "$lib/styles/Dropdown.scss";
import Link from "$lib/components/Link.svelte";
interface DropdownItem {
text: string;
redirectFunc: () => void;
hotkey?: string;
}
export let items: DropdownItem[] = [];
export let label: string = "Dropdown";
let isOpen: boolean = false;
function toggleDropdown(): void {
isOpen = !isOpen;
}
function handleClickOutside(event: MouseEvent): void {
if (isOpen && !(event.target as HTMLElement).closest(".dropdown")) {
isOpen = false;
}
}
</script>
<svelte:window on:click={handleClickOutside} />
<div class="dropdown {$$props.class}">
<button on:click={toggleDropdown} class="dropdown-toggle {$$props.class}">
{label}
<span class="dropdown-arrow">{isOpen ? "▲" : "▼"}</span>
</button>
{#if isOpen}
<div class="dropdown-menu">
{#each items as item}
<div class="dropdown-item-wrapper">
<Link
text={item.text}
redirectFunc={item.redirectFunc}
hotkey={item.hotkey || ""}
class="dropdown-item {$$props.class}"
/>
</div>
{/each}
</div>
{/if}
</div>

View File

@@ -0,0 +1,25 @@
<script>
import katex from "katex";
export let math;
export let displayMode = false;
const options = {
displayMode: displayMode,
throwOnError: false,
};
$: katexString = katex.renderToString(math, options);
</script>
<svelte:head>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css"
integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X"
crossorigin="anonymous"
/>
</svelte:head>
<span class={$$props.class}>
{@html katexString}
</span>

View File

@@ -68,6 +68,12 @@
hotkey="d" hotkey="d"
redirectFunc={navigation.toRepository} redirectFunc={navigation.toRepository}
/> />
<Link
class="navigation-footer-link"
text="Data Methodology"
hotkey="d"
redirectFunc={navigation.toMethodology}
/>
<Link <Link
class="navigation-footer-link" class="navigation-footer-link"
text="How to Contribute" text="How to Contribute"

View File

@@ -1,5 +1,6 @@
<script> <script>
import "$lib/styles/NavigationHeader.scss"; import "$lib/styles/NavigationHeader.scss";
import Dropdown from "$lib/components/Dropdown.svelte";
import Button from "$lib/components/Button.svelte"; import Button from "$lib/components/Button.svelte";
import Link from "$lib/components/Link.svelte"; import Link from "$lib/components/Link.svelte";
@@ -13,6 +14,11 @@
export let display_logo = true; export let display_logo = true;
import { navigation } from "$lib/navigation"; import { navigation } from "$lib/navigation";
const dataItems = [
{ text: "Repository", redirectFunc: navigation.toRepository, hotkey: "dr" },
{ text: "Methodology", redirectFunc: navigation.toMethodology, hotkey: "dm" },
];
</script> </script>
<div class={$$props.class}> <div class={$$props.class}>
@@ -26,12 +32,7 @@
redirectFunc={navigation.toHome} redirectFunc={navigation.toHome}
/> />
{/if} {/if}
<Link <Dropdown label="Data" items={dataItems} class="navigation-header-link {link_class}" />
class="navigation-header-link {link_class}"
text="Data Repository"
hotkey="d"
redirectFunc={navigation.toRepository}
/>
<Link <Link
class="navigation-header-link {link_class}" class="navigation-header-link {link_class}"
text="How to Contribute" text="How to Contribute"

View File

@@ -8,6 +8,7 @@ export const navigation = {
toRepository: () => { toRepository: () => {
window.location.href = "https://invenio.am-d-model.eu/"; window.location.href = "https://invenio.am-d-model.eu/";
}, },
toMethodology: () => goto("/methodology"),
to404: () => { to404: () => {
throw error(404, "Page not found"); throw error(404, "Page not found");
}, },

View File

@@ -0,0 +1,47 @@
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-toggle {
background-color: transparent;
border: none;
cursor: pointer;
display: flex;
align-items: center;
gap: 5px;
padding: 0px 8px 0px 8px;
}
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
background-color: white;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
min-width: 150px;
z-index: 10;
padding: 8px;
}
.dropdown-item-wrapper {
display: block;
padding: 8px;
}
:global(.dropdown-item) {
display: block;
padding: 8px 16px;
width: 100%;
text-align: left;
}
:global(.dropdown-item:hover) {
background-color: #f5f5f5;
}
.dropdown-arrow {
font-size: 0.7em;
}

View File

@@ -18,9 +18,31 @@ h5,
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
} }
table {
font-size: 24pt;
border-collapse: collapse;
width: 100%;
}
th,
td {
border: 1px solid #ddd;
padding: 8px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
menu, menu,
ol, ol,
ul { ul,
dl {
list-style-type: none; list-style-type: none;
list-style-position: inside; list-style-position: inside;
margin: 0; margin: 0;
@@ -67,6 +89,12 @@ p {
padding-bottom: 24px; padding-bottom: 24px;
} }
@media (max-width: 620px) {
table {
font-size: 18pt;
}
}
@media (max-width: 620px) { @media (max-width: 620px) {
h1 { h1 {
font-size: 54pt; font-size: 54pt;
@@ -82,7 +110,8 @@ p {
} }
ol, ol,
ul { ul,
dl {
font-size: 16pt; font-size: 16pt;
} }
} }
@@ -101,13 +130,19 @@ p {
font-size: 16pt; font-size: 16pt;
} }
table,
ol, ol,
ul { ul,
dl {
font-size: 14pt; font-size: 14pt;
} }
} }
@media (max-width: 380px) { @media (max-width: 380px) {
table {
font-size: 16pt;
}
h1 { h1 {
font-size: 36pt; font-size: 36pt;
} }
@@ -121,8 +156,10 @@ p {
font-size: 16pt; font-size: 16pt;
} }
table,
ol, ol,
ul { ul,
dl {
font-size: 14pt; font-size: 14pt;
} }
} }

View File

@@ -18,7 +18,7 @@
text-align: left; text-align: left;
font-size: var(--navigation-header-font-size); font-size: var(--navigation-header-font-size);
font-weight: var(--navigation-header-font-weight); font-weight: var(--navigation-header-font-weight);
text-decoration: underline; border-bottom: 1px solid currentColor; // instead of an underline
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -0,0 +1,361 @@
<script>
import "./Methodology.scss";
import NavigationHeader from "$lib/components/NavigationHeader.svelte";
import NavigationFooter from "$lib/components/NavigationFooter.svelte";
import Latex from "$lib/components/Latex.svelte";
import { CDN } from "$lib/constants";
const laser_params = [
{ name: "Laser Power (P)", values: [80, 120, 160, 200], unit: "W" },
{ name: "Scan Speed (V)", values: [600, 800, 1000, 1200], unit: "mm/s" },
{ name: "Hatch Spacing (H)", values: [60, 90, 120, 150], unit: "µm" },
{ name: "Spot Size (f)", values: [80, 90, 100, 110], unit: "µm" },
];
const ved_params = [
{
name: "Volumetric Energy Density based on spot size (VED<sub>f</sub>)",
min: 4.04,
max: 69.44,
unit: "J/mm<sup>3</sup>",
},
{
name: "Volumetric Energy Density based on hatch spacing (VED<sub>H</sub>)",
min: 8.89,
max: 111.11,
unit: "J/mm<sup>3</sup>",
},
];
const vedf_eq = "VED_f=\\frac{P}{V \\times L \\times f}\\space\\left( \\frac{J}{mm^3} \\right)";
const vedh_eq = "VED_H=\\frac{P}{V \\times L \\times H}\\space\\left( \\frac{J}{mm^3} \\right)";
const pyrometry_params = [
{ name: "Measurable temperature range", desc: "5002500 °C" },
{ name: "Field of view", desc: "0.5 mm" },
{ name: "Spectral range", desc: "1.581.80 µm" },
{ name: "Response time (T90)", desc: "10 µs" },
{ name: "Resolution", desc: "10-bit" },
{ name: "Data acquisition rate", desc: "100 kHz" },
];
/**
* @typedef {Object} DataRow
* @property {number} x - X coordinate
* @property {number} y - Y coordinate
* @property {number} t1 - First temperature
* @property {number} t2 - Second temperature
*/
/**
* @type {{
* headers: Array<keyof DataRow>,
* data: DataRow[]
* }}
*/
const ir_table = {
headers: ["x", "y", "t1", "t2"],
data: [
{ x: -20139, y: -15428, t1: 820, t2: 820 },
{ x: -20139, y: -15428, t1: 804, t2: 804 },
{ x: -20139, y: -15428, t1: 811, t2: 811 },
{ x: -20139, y: -15428, t1: 803, t2: 803 },
{ x: -20139, y: -15428, t1: 812, t2: 812 },
{ x: -20139, y: -15428, t1: 812, t2: 812 },
{ x: -20139, y: -15428, t1: 808, t2: 808 },
{ x: -20139, y: -15428, t1: 815, t2: 815 },
{ x: -20139, y: -15428, t1: 808, t2: 808 },
{ x: -20139, y: -15428, t1: 815, t2: 815 },
{ x: -20139, y: -15428, t1: 799, t2: 799 },
],
};
</script>
<div class="methodology">
<NavigationHeader />
<main>
<div class="copy">
<h1>Methodology</h1>
<p>
This page describes the methodology being used for sample fabrication and in-situ IR
pyrometry being used by the AM-D-Model project. Data contributions to the project
should follow a similar methodology to this, to ensure data consistency in the
resulting benchmark. As part of our commitment to openness and transparency, we
encourage collaborators and interested parties to review our methodology and engage
with our team. We welcome any and all suggestions for potential improvements and
discussions on how we can ensure that this project produces a valuable benchmark
dataset that can drive the future development of metal AM.
</p>
</div>
<div class="copy">
<section>
<h2>Component Geometry and Specification</h2>
<div class="copy-with-figure">
<div class="copy">
<p>
The geometry of the test AM components (samples) shown in Figure 1
consist of a 7mm × 7mm × 7.2mm (L x B x H) cuboid, complemented with a
tapered support structure of height, 2.85 mm. Additionally, sample
numbers with a height of 300 µm were incorporated into the top of the
cuboid geometry, resulting in a total sample dimension of 7mm × 7mm ×
10.35 mm. This geometry, along with the support structure design, was
specifically chosen to enable straightforward sample removal using a wet
abrasive cutter equipped with 2.8 mm thick blades, while also ensuring
easy handling during characterization.
</p>
</div>
<div class="figure-column">
<figure>
<img
src="{CDN}/methodology_fig1.webp"
alt="A CAD model projection of one of the samples produced."
/>
<figcaption>
<b>Figure 1.</b> CAD representations of the sample geometry:
<i>(a)</i>
isometric view, and <i>(b)</i> front view.
</figcaption>
</figure>
</div>
</div>
</section>
</div>
<div class="copy">
<section>
<h2>AM Pilot Line and Process Parameters</h2>
<p>
The samples were fabricated using the AM pilot line at Dublin City University
(DCU). This pilot line is the AconityMINI® 3D powder bed fusion-laser system.
It is equipped with a 200 W, 1068 nm Yb- fiber laser. This system supports laser
scanning speeds of up to 2000 mm/s and features a minimum laser beam diameter of
32 µm. High-purity argon gas (99.99999% purity) was used as shielding gas, and
the "Skywriting" feature was enabled during the fabrication process. A
comprehensive PBF-LB process parameter window was defined through a
full-factorial experimental design. This approach systematically explores the
effects of key process parameters by varying four factors at four levels each (4
factors × 4 levels = 4<sup>4</sup>), resulting in a total of 256 unique
parameter combinations. The factors and their corresponding levels are as
follows:
</p>
<div class="laser-param-list">
<dl>
{#each laser_params as param}
<div>
<dt>{@html param.name}:</dt>
<dd>[ {@html param.values.join(", ")} ] {@html param.unit}</dd>
</div>
{/each}
</dl>
</div>
<p>
The range of energy densities calculated from these parameters spans the
following:
</p>
<div class="ved-param-list">
<dl>
{#each ved_params as param}
<div>
<dt>{@html param.name}:</dt>
<dd>
[ {@html param.min} to {@html param.max} ] {@html param.unit}
</dd>
</div>
{/each}
</dl>
</div>
<p>
The metal powder feedstock used was the PowderRange® 316L stainless steel
powder supplied by Carpenter Additive®. The particle size of the powder
feedstock ranged between 15 and 45 µm. For this reason, the layer thickness (L)
parameter was maintained at a constant value of 50 µm. At this layer thickness,
each sample with dimensions of 7 mm × 7 mm × 10.3 mm required 206 layers to
complete fabrication. A bidirectional scanning strategy was applied, starting
with a layer angle of 45 degrees, followed by a 90° rotation for each subsequent
layer.
</p>
<div class="copy-with-figure">
<div class="copy">
<p>
Two sets of the 256 unique parameter combinations were fabricated,
yielding a total of 512 samples. Figure 2 shows representative pictures
of the first 100 samples produced. During the final print session, 56
remaining samples from the first set were combined with 56 remaining
samples from the second set, creating a final print batch with 112
samples. This method was implemented to maintain consistent interlayer
printing times and achieve thermal distribution uniformity across all
samples, comparable to the other print batches of 100 samples.
</p>
</div>
<div class="figure-column">
<figure>
<img
src="{CDN}/methodology_fig2.webp"
alt="2 photographs of a PBF buildplate featuring 100 samples."
/>
<figcaption>
<b>Figure 2.</b> Exemplar pictures of 100 fabricated samples still
attached to the build plate <i>(a)</i> top view and <i>(b)</i> angled
view.
</figcaption>
</figure>
</div>
</div>
<p>
Volumetric Energy Density (VED) is a derived thermodynamic metric widely used in
AM industry and reported in metal AM research. It is typically expressed as
either the spot size variant (<i>VED<sub>f</sub></i>) or the hatch spacing
variant (<i>VED<sub>H</sub></i>), calculated using the below equations,
respectively:
</p>
<div class="equation-container">
<Latex math={vedf_eq} class="equation" displayMode />
</div>
<div class="equation-container">
<Latex math={vedh_eq} class="equation" displayMode />
</div>
<p>
However, these two VED variants are not directly comparable, as neither
exclusively captures the full complexity of melt pool physics. This includes
melt pool formation and propagation, solidification geometry (width and depth),
and the intricate mass and heat transfer between the melt pool and the
surrounding material. Given these limitations, both <i>VED<sub>f</sub></i> and
<i>VED<sub>H</sub></i> are included as PBF-LB process-based features. The inclusion
of these two distinct measures of volumetric energy density, further enriches the
experimental space, enabling a nuanced exploration of the relevance of energy distribution
to the ML model performance.
</p>
</section>
<section>
<h2>Infrared (IR) Pyrometry</h2>
<p>
IR pyrometry measures thermal radiation from the melt pools during the PBF-LB
process, enabling real-time recording of temperature distributions. This helps
identify issues such as overheating, insufficient melting, or thermal gradients
that may cause defects or residual stresses.
</p>
<div class="copy-with-figure">
<div class="figure-column">
<figure>
<img
src="{CDN}/methodology_fig3.webp"
alt="2 photographs of a PBF buildplate featuring 100 samples."
/>
<figcaption>
<b>Figure 3.</b> Installed in-situ monitoring modules in the
<i>(a)</i>
<a
class="text-blue-700"
href="https://aconity3d.com/products/aconity-mini/"
>AconityMINI PBF-LB machine</a
>
at DCU; <i>(b)</i> two
<a
class="text-blue-700"
href="https://www.kleiberinfrared.com/index.php/en/products/highspeed/series-740-lo-730-lo/series-740-lo.html"
>Kleiber® KG 740-LO pyrometers</a
>
in-line with the laser beam path; <i>(c)</i>
<a class="text-blue-700" href="https://amiquam.net/"
>AMiquam W1 ECM module</a
>
with two channels; and <i>(d)</i> one
<a
class="text-blue-700"
href="https://avisoft.com/ultrasound-microphones/cm16-cmpa/"
>Avisoft-Bioacoustics® CM16/CMPA ultrasonic microphone</a
>.
</figcaption>
</figure>
</div>
<div class="copy">
<p>
In-situ temporal IR monitoring was performed using two
<a
href="https://www.kleiberinfrared.com/index.php/en/products/highspeed/series-740-lo-730-lo/series-740-lo.html"
>Kleiber® KG 740-LO pyrometers</a
>
fitted to our AconityMINI machine (Figure 3a). The optical path of both pyrometers
was configured to be in line with the laser beam path (see Figure 3b). This
enabled the capturing of the meltpool positions (x, y) with the corresponding
relative temperature of the meltpool (T) of all samples being fabricated.
The pyrometers were calibrated to a black-body standard to the same temperature
range, and features:
</p>
</div>
</div>
<div class="copy">
<div class="pyrometry-param-list">
<dl>
{#each pyrometry_params as param}
<div>
<dt>{@html param.name}:</dt>
<dd>{@html param.desc}</dd>
</div>
{/each}
</dl>
</div>
</div>
</section>
<section>
<h2>Relative Density</h2>
<p>
The target material property is the observed relative density (RD) of the test
samples, expressed as a percentage of the theoretical density of a perfectly
dense specimen. The RD of each sample was determined using Archimedes
principle, following the ASTM B962-23 standard. Ethanol served as the immersion
fluid for the measurements, and the assumed theoretical density of 316L -SS was
to be 8000 kg/m<sup>3</sup> for these calculations.
</p>
</section>
<section>
<h2>Sensor Data</h2>
<p>
The collected data from the sensors form a comprehensive dataset designed to
capture various aspects of the PBF-LB process. This dataset integrates
measurements from multiple sources, ensuring a detailed representation of the
process parameters and their influence on the target material property
prediction.
</p>
</section>
<section>
<h2>Infrared Pyrometry (IR) Data</h2>
<p>
IR data is stored as layer-by-layer .pcd files, where the filename represents
the layer thickness (e.g., 5.24.pcd corresponds to IR data at a 5.24 mm layer
thickness). Each file contains meltpool coordinates (x, y) and relative meltpool
temperature (in degrees Celsius) from the two pyrometers, as illustrated in
Table 1.
</p>
<figure>
<figcaption>
<b>Table 1:</b> Raw IR data structure
</figcaption>
<table>
<thead>
<tr>
{#each ir_table.headers as header}
<th>{header}</th>
{/each}
</tr>
</thead>
<tbody>
{#each ir_table.data as row}
<tr>
{#each ir_table.headers as header}
<td>{row[header]}</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</figure>
</section>
</div>
</main>
<NavigationFooter />
</div>

View File

@@ -0,0 +1,190 @@
main {
padding: 5% 5% 5% 5%;
}
p {
text-align: justify;
}
figcaption {
text-align: center;
padding: 4px 0 4px 0;
}
.methodology,
.methodology * {
box-sizing: border-box;
}
.methodology {
background: var(--cpalettecomplimentary);
width: 100vw;
min-width: 250px;
position: absolute;
display: flex;
flex-direction: column;
}
.copy {
padding: 0 8px 0 8px;
}
.copy-with-figure {
@apply grid grid-cols-1 gap-8;
@media (min-width: 768px) {
@apply grid-cols-2
}
div {
padding: 0;
display: flex;
align-items: center;
justify-content: center;
}
}
.param-list {
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 24px;
dl {
@apply space-y-2;
div {
@apply items-start;
display: flex;
align-items: center;
}
}
dl,
dt,
dd {
font-size: 24pt;
@media (max-width: 820px) {
font-size: 18pt;
}
@media (max-width: 620px) {
font-size: 14pt;
}
@media (max-width: 420px) {
font-size: 12pt;
}
@media (max-width: 380px) {
font-size: 10pt;
}
}
dt {
@apply font-semibold text-gray-700;
}
dd {
@apply flex-1 text-gray-500;
}
}
.laser-param-list {
@extend .param-list;
dt {
width: 416px;
@media (max-width: 820px) {
width: 256px;
}
@media (max-width: 620px) {
width: 184px;
}
@media (max-width: 420px) {
width: 142px;
}
@media (max-width: 380px) {
width: 112px;
}
}
}
.ved-param-list {
@extend .param-list;
dt {
width: 832px;
@media (max-width: 1280px) {
width: 532px;
padding-bottom: 16px
}
@media (max-width: 1024px) {
width: 410px;
}
@media (max-width: 820px) {
width: 256px;
}
@media (max-width: 514px) {
width: 128px;
}
}
}
.equation-container {
padding: 8px 0 8px 0;
}
.equation {
font-size: 36px;
@media (max-width: 720px) {
font-size: 24px;
}
@media (max-width: 480px) {
font-size: 18px;
}
@media (max-width: 370px) {
font-size: 16px;
}
@media (max-width: 300px) {
font-size: 12px;
}
}
.pyrometry-param-list {
@extend .param-list;
dt {
width: 512px;
@media (max-width: 820px) {
width: 352px;
}
@media (max-width: 620px) {
width: 184px;
}
@media (max-width: 420px) {
width: 142px;
}
@media (max-width: 380px) {
width: 112px;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

13
tsconfig.json Normal file
View File

@@ -0,0 +1,13 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true
}
}