Skip to content

Commit

Permalink
Added getter for material properties and applied PR requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianarce-elemwave committed Jan 10, 2025
1 parent 8644e80 commit d04db03
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 64 deletions.
154 changes: 154 additions & 0 deletions doc/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,157 @@ Once the environment is loaded, follow the steps in the next section.
- Launch the project by pressing **F5** to begin debugging.

Following these steps, the project should be set up and ready to compile and debug in Visual Studio 2019 with Intel tools.

## WSL2 + Visual Studio Code + GFortran Setup Guide

### Prerequisites

- **Windows 10** (version 1903 or higher) or **Windows 11**
- **WSL2** installed
- **Visual Studio Code (VSCode)** installed on Windows

### Step 1: Install WSL2

#### 1.1 Install WSL (Windows Subsystem for Linux)

1. Open **PowerShell** as Administrator and run the following command to enable the required features:

```bash
wsl --install
wsl --set-default-version 2
```

2. After installation is complete, you can choose a Linux distribution from the Microsoft Store (e.g., Ubuntu). for example if you want to install Ubuntu:

```bash
wsl --install -d Ubuntu-24.04
```


3. Launch the installed distribution from the Start menu, and it will complete the installation by setting up a user.

### Step 2: Install Visual Studio Code

#### 2.1 Download Visual Studio Code
Go to the official Visual Studio Code website and download the installer:
https://code.visualstudio.com/

Once downloaded, double-click the installer and follow the on-screen instructions to complete the installation.

#### 2.2 Launch Visual Studio Code

After the installation is complete, you can open Visual Studio Code either by:
- Searching for "Visual Studio Code" in the Start Menu
- Or by launching the VSCode application from the shortcut created during installation.

#### 2.3 Installing VSCode Extensions

To work with these project is mandatory to install the next extensions

- Modern Fortran (Fortran development)
- Python (Python development)
- C/C++ (C/C++ development)
- CMake (CMake integration)
- C++ TestMate (C++ testing)
- Remote - WSL

#### 2.4 Connect to WSL2

After installing the Remote - WSL extension, follow these steps to open VSCode in the WSL2 environment:
1. Press Ctrl + Shift + P to open the Command Palette.
2. Type `Remote-WSL: New Window` and press Enter.
3. VSCode will open a new window and connect to your default WSL2 distribution.

Now you're set up to work with your WSL2 environment directly from VSCode

Now we are ready to clone the repo

#### Step 1: Clone the Repository
```bash
git clone <repository_url>
cd <repository_name>
```

This project has submodule dependencies remember to initiate an update the

```bash
git submodule init
git submodule update
```

#### Step 2: Install Python Requirements

If the project has Python dependencies listed in a requirements.txt file, you can install them using the following command:

1. Make sure you have Python and pip installed on your system. It is recomended to use a venv.
2. Run the following command to install the required dependencies:

```bash
python3 -m pip install -r requirements.txt
```

#### Step 3: Install hdf5 dependencies
It is needed to install manually the hdf5 dependencies. On the terminal type the next command:
```
sudo apt install libhdf5-dev libopenmpi-dev
```
#### Step 4: Build the Project with CMake

Now, you need to build the project using CMake.

1. Open the Command Palette in Visual Studio Code by pressing Ctrl + Shift + P.
2. Type CMake: Build and select it from the list of commands.

This will trigger the build process using the current CMake configuration.


#### Step 5: Change CMake Settings (Optional)

If you want to modify the CMake settings (such as build options or configurations), follow these steps:

1. Open the Command Palette in Visual Studio Code by pressing Ctrl + Shift + P.
2. Type CMake: Configure and select it from the list of commands.

This will open the CMake configuration interface where you can modify build settings.

3. After making any changes to the settings, rebuild the project by running the CMake: Clean Rebuild command again from the Command Palette.


#### Step 6: Configure and Run Python Tests

To run Python unit tests, you need to configure the testing framework.

1. Open the Command Palette in Visual Studio Code by pressing Ctrl + Shift + P.
2. Type Python: Configure Tests and select it from the list of commands.
3. When prompted, select unittest as the testing framework.
4. Select the folder containing your test files. Typically, this folder is named tests or something similar. Once selected, Visual Studio Code will automatically configure and discover the tests.

To run the tests:

1. Open the Command Palette again by pressing Ctrl + Shift + P.
2. Type Python: Run All Tests to run the unit tests in your project.

## Debugging the project

For a correct debugging experience is needed to configure a launch.json file. This file usually is created by vscode automatically. In case it does not exist. You can create your own on .vscode folder.

An example of launch.json filke is given. This will use a file as argument when calling to semba-fdtd.
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Fortran Launch (GDB)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/build/bin/semba-fdtd",
"miDebuggerPath": "gdb",
"args": ["-i", "shieldingEffectiveness.fdtd.json"],
"stopAtEntry": false,
"cwd": "${workspaceRoot}/tmp_cases/sgbcShieldingEffectiveness/"
}
]
}
```

Now you are ready to work with the project.
6 changes: 6 additions & 0 deletions src_pyWrapper/pyWrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,9 @@ def getVTKMap(self):
mapFile = os.path.join(current_path, folders[0], folders[0]+"_1.vtk")
assert os.path.isfile(mapFile)
return mapFile

def getMaterialProperties(self, materialName):
if 'materials' in self._input:
for idx, element in enumerate(self._input['materials']):
if element["name"] == materialName:
return self._input['materials'][idx]
57 changes: 28 additions & 29 deletions test/pyWrapper/test_full_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,69 +270,68 @@ def test_sgbc_shielding_effectiveness(tmp_path):

assert np.allclose(fdtd_s21_db, anal_s21_db, rtol=0.05)

def test_dielectric_refraction(tmp_path):
def test_dielectric_transmission(tmp_path):
_FIELD_TOLERANCE = 0.05
_RELATIVE_PERMITTIVITY = 4

def getIncidentField(probe:Probe) -> Dict:
idx = probe.df['field'].argmin()
time = probe.df['time'][idx]
value = probe.df['field'][idx]
idx = probe["field"].argmin()
time = probe["time"][idx]
value = probe["field"][idx]
return {"time":time, "value": value}

def getReflectedField(probe:Probe) -> Dict:
idx = probe.df['field'].argmax()
time = probe.df['time'][idx]
value = probe.df['field'][idx]
idx = probe["field"].argmax()
time = probe["time"][idx]
value = probe["field"][idx]
return {"time":time, "value": value}

def getRefractedField(probe:Probe) -> Dict:
idx = probe.df['field'].argmin()
time = probe.df['time'][idx]
value = probe.df['field'][idx]
def getTransmitedField(probe:Probe) -> Dict:
idx = probe["field"].argmin()
time = probe["time"][idx]
value = probe["field"][idx]
return {"time":time, "value": value}

def getReflectedDelay(incidentTime:float, reflectedTime:float):
timeToSurface:float = ((reflectedTime-incidentTime)/2) + incidentTime
reflectedDelay:float = reflectedTime - timeToSurface
return reflectedDelay

def getRefractedDelay(incidentTime:float, reflectedTime:float, refractedTime:float):
def getTransmitedDelay(incidentTime:float, reflectedTime:float, transmitedTime:float):
timeToSurface:float = ((reflectedTime-incidentTime)/2) + incidentTime
refractedDelay = refractedTime - timeToSurface
return refractedDelay

materialRelativeImpedance = np.sqrt(1/_RELATIVE_PERMITTIVITY)
expectedReflectedCoeff = (materialRelativeImpedance - 1) / (materialRelativeImpedance + 1)
expectedRefractedCoeff = (1 + expectedReflectedCoeff)
transmitedDelay = transmitedTime - timeToSurface
return transmitedDelay

expectedDelayRatio = 1/np.sqrt(_RELATIVE_PERMITTIVITY)

fn = CASES_FOLDER + "dielectric_refraction/dielectricRefraction.fdtd.json"
fn = CASES_FOLDER + "dielectric/dielectricTransmission.fdtd.json"
solver = FDTD(fn, path_to_exe=SEMBA_EXE, run_in_folder=tmp_path)

solver.run()
assert solver.hasFinishedSuccessfully()

relativePermittivity = solver.getMaterialProperties('DielectricMaterial')["relativePermittivity"]
materialRelativeImpedance = np.sqrt(1/relativePermittivity)

expectedReflectedCoeff = (materialRelativeImpedance - 1) / (materialRelativeImpedance + 1)
expectedtransmitedCoeff = (1 + expectedReflectedCoeff)
expectedDelayRatio = 1/np.sqrt(relativePermittivity)

outsideProbe = Probe(solver.getSolvedProbeFilenames("outside")[0])
insideProbe = Probe(solver.getSolvedProbeFilenames("inside")[0])

time = outsideProbe.df['time']
time = outsideProbe["time"]
dt = time[1] - time[0]
fq = fftfreq(len(time))/dt

incidentField = getIncidentField(outsideProbe)
reflectedField = getReflectedField(outsideProbe)
refractedField = getRefractedField(insideProbe)
transmitedField = getTransmitedField(insideProbe)

assert (incidentField['value'] - refractedField['value'] + reflectedField['value']) < _FIELD_TOLERANCE
assert (incidentField['value'] - transmitedField['value'] + reflectedField['value']) < _FIELD_TOLERANCE
assert np.allclose(reflectedField["value"]/incidentField["value"], expectedReflectedCoeff, rtol=_FIELD_TOLERANCE)
assert np.allclose(refractedField["value"]/incidentField["value"], expectedRefractedCoeff, rtol=_FIELD_TOLERANCE)
assert np.allclose(transmitedField["value"]/incidentField["value"], expectedtransmitedCoeff, rtol=_FIELD_TOLERANCE)

reflectedDelay:float = getReflectedDelay(incidentField['time'], reflectedField['time'])
refractedDelay:float = getRefractedDelay(incidentField['time'], reflectedField['time'], refractedField['time'])
transmitedDelay:float = getTransmitedDelay(incidentField['time'], reflectedField['time'], transmitedField['time'])

assert np.allclose(reflectedDelay/refractedDelay, expectedDelayRatio, rtol=_FIELD_TOLERANCE)
assert np.allclose(reflectedDelay/transmitedDelay, expectedDelayRatio, rtol=_FIELD_TOLERANCE)



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@
},
"coordinates": [
{"id": 1, "relativePosition": [1, 1, 40]},
{"id": 2, "relativePosition": [1, 1, 160]},
{"id": 3, "relativePosition": [1, 1, 5]}
{"id": 2, "relativePosition": [1, 1, 160]}
],
"elements": [
{"id": 1, "type": "node", "coordinateIds": [1]},
{"id": 2, "type": "node", "coordinateIds": [2]},
{"id": 3, "type": "node", "coordinateIds": [3]},
{"id": 4, "type": "cell", "intervals": [ [ [-1, -1, 0], [3,3,10] ] ]},
{"id": 5, "type": "cell", "intervals": [[ [0, 0, 100], [2,2,200] ]]}
{"id": 3, "type": "cell", "intervals": [ [ [-1, -1, 0], [3,3,10] ] ]},
{"id": 4, "type": "cell", "intervals": [[ [0, 0, 100], [2,2,200] ]]}
]
},

Expand All @@ -48,7 +46,7 @@
{
"type": "planewave",
"magnitudeFile": "gauss.exc",
"elementIds": [4],
"elementIds": [3],
"direction": {
"theta": 0.0,
"phi": 0.0
Expand All @@ -62,9 +60,8 @@

"materialAssociations": [
{
"type": "bulk",
"materialId": 1,
"elementIds": [ 5 ]
"elementIds": [ 4 ]
}
],

Expand All @@ -88,16 +85,6 @@
"domain": {
"type": "time"
}
},
{
"name": "reflected",
"type": "point",
"field": "electric",
"elementIds": [3],
"directions": ["x"],
"domain": {
"type": "time"
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,46 +53,41 @@

plt.grid()
# %%
fn = 'dielectricRefraction.fdtd.json'
fn = 'dielectricTransmission.fdtd.json'
solver = FDTD(input_filename = fn, path_to_exe=SEMBA_EXE)
solver.cleanUp()
solver.run()
assert solver.hasFinishedSuccessfully()

#%%
outside = Probe(solver.getSolvedProbeFilenames("outside")[0])
plt.plot(outside.df['time'], outside.df['field'], label='outside')
plt.plot(outside["time"].to_numpy(), outside["field"].to_numpy(), label='outside')
plt.xlim(0, 5e-8)
plt.legend()
#%%
inside = Probe(solver.getSolvedProbeFilenames("inside")[0])
plt.plot(inside.df['time'], inside.df['field'], label='inside')
plt.xlim(0, 5e-8)
plt.legend()
#%%
reflected = Probe(solver.getSolvedProbeFilenames("reflected")[0])
plt.plot(reflected.df['time'], reflected.df['field'], label='reflected')
plt.plot(inside["time"].to_numpy(), inside["field"].to_numpy(), label='inside')
plt.xlim(0, 5e-8)
plt.legend()

# %%
incidentPulseIndex = outside.df['field'].argmin()
reflectedPulseIndex = outside.df['field'].argmax()
refractedPulseIndex = inside.df['field'].argmin()
incidentPulseIndex = outside['field'].argmin()
reflectedPulseIndex = outside['field'].argmax()
refractedPulseIndex = inside['field'].argmin()

# %%
incidentPulse = outside.df['field'][incidentPulseIndex]
reflectedPulse = outside.df['field'][reflectedPulseIndex]
refractedPulse = inside.df['field'][refractedPulseIndex]
incidentPulse = outside['field'][incidentPulseIndex]
reflectedPulse = outside['field'][reflectedPulseIndex]
refractedPulse = inside['field'][refractedPulseIndex]
pulses = [
incidentPulse,
reflectedPulse,
refractedPulse
]

incidentTime = outside.df['time'][incidentPulseIndex]
reflectedTime = outside.df['time'][reflectedPulseIndex]
refractedTime = inside.df['time'][refractedPulseIndex]
incidentTime = outside["time"][incidentPulseIndex]
reflectedTime = outside["time"][reflectedPulseIndex]
refractedTime = inside["time"][refractedPulseIndex]

times = [
incidentTime,
Expand Down
File renamed without changes.

0 comments on commit d04db03

Please sign in to comment.