Skip to content

Commit c46dbe1

Browse files
authored
Merge pull request #197 from OpenSEMBA/dev
Dev
2 parents 08b3ead + 3b606b2 commit c46dbe1

File tree

58 files changed

+110942
-1694
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+110942
-1694
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,4 @@ tmp/
6565
tmp_cases/
6666
testData/outputs/paul/paul_8.6_square.txt
6767
testing_hdf5_writing_and_reading.h5
68+
build

CMakeLists.txt

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
5656
if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
5757
message(STATUS "Using GNU flags")
5858

59-
add_definitions(-DCompileWithIncludeMpifh)
6059
set(CMAKE_CXX_FLAGS "-fopenmp")
6160
set(CMAKE_Fortran_FLAGS "-fopenmp -ffree-form -ffree-line-length-none -fdec -fallow-argument-mismatch")
6261

@@ -173,6 +172,13 @@ add_library(semba-types
173172
"src_wires_pub/wires_types.F90"
174173
"src_main_pub/lumped_types.F90"
175174
)
175+
target_link_libraries(semba-types ${MPI_Fortran_LIBRARIES})
176+
177+
add_library(semba-reports
178+
"src_main_pub/errorreport.F90"
179+
"src_main_pub/snapxdmf.F90"
180+
)
181+
target_link_libraries(semba-reports semba-types ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES})
176182

177183
if(SEMBA_FDTD_ENABLE_SMBJSON)
178184
add_subdirectory(src_json_parser)
@@ -200,7 +206,6 @@ endif()
200206

201207
if(SEMBA_FDTD_COMPONENTS_LIB)
202208
add_library(semba-components
203-
"src_main_pub/errorreport.F90"
204209
"src_main_pub/anisotropic.F90"
205210
"src_main_pub/borderscpml.F90"
206211
"src_main_pub/bordersmur.F90"
@@ -217,19 +222,21 @@ if(SEMBA_FDTD_COMPONENTS_LIB)
217222
"src_wires_pub/wires.F90"
218223
"src_wires_pub/wires_mtln.F90"
219224
)
220-
target_link_libraries(semba-components semba-types ${MTLN_LIBRARIES})
225+
target_link_libraries(semba-components semba-types semba-reports ${MTLN_LIBRARIES})
221226
endif()
222227

223228
if(SEMBA_FDTD_OUTPUTS_LIB)
224229
add_library(semba-outputs
225230
"src_main_pub/mpicomm.F90"
226231
"src_main_pub/observation.F90"
227232
"src_main_pub/vtk.F90"
228-
"src_main_pub/snapxdmf.F90"
229233
"src_main_pub/xdmf.F90"
230234
"src_main_pub/xdmf_h5.F90"
231235
)
232-
target_link_libraries(semba-outputs semba-components ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES})
236+
target_link_libraries(semba-outputs
237+
semba-components
238+
${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES}
239+
${MPI_Fortran_LIBRARIES})
233240
endif()
234241

235242
if(SEMBA_FDTD_MAIN_LIB)
@@ -247,14 +254,17 @@ if(SEMBA_FDTD_MAIN_LIB)
247254
"src_main_pub/resuming.F90"
248255
"src_main_pub/timestepping.F90"
249256
)
250-
target_link_libraries(semba-main semba-outputs ${SMBJSON_LIBRARIES} ${MTLN_LIBRARIES})
257+
target_link_libraries(semba-main
258+
semba-outputs
259+
${SMBJSON_LIBRARIES}
260+
${MTLN_LIBRARIES})
251261
endif()
252262

253263
if (SEMBA_FDTD_EXECUTABLE)
254264
add_executable(semba-fdtd
255265
"src_main_pub/semba_fdtd.F90"
256266
)
257-
target_link_libraries(semba-fdtd semba-main)
267+
target_link_libraries(semba-fdtd semba-main semba-reports)
258268
target_link_libraries(semba-fdtd ${MPI_Fortran_LIBRARIES})
259269
endif()
260270

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ In a nutshell, semba-fdtd capabilities are
3939

4040
Compilation and debugging instructions can be found [here](doc/development.md).
4141

42+
A short tutorial on usage can be found [here](doc/tutorials/veritasium/veritasium.md).
43+
4244
The main binary is `semba-fdtd` which uses [the SMBJSON format](doc/smbjson.md) as input files.
4345
It can be run with
4446

@@ -48,6 +50,7 @@ It can be run with
4850

4951
Tests must be run from the root folder. `python` wrapper test assumes that `semba-fdtd` has been compiled successfully and is located in folder `build/bin/`. For intel compilation it also assumes that the intel runtime libraries are accessible.
5052

53+
5154
# License
5255

5356
This code is licensed under the terms of the [MIT License](LICENSE). All rights reserved by the University of Granada (Spain)

doc/smbjson.md

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,17 @@ Each entry in `terminations` is specified by a `type`
453453

454454
+ `short` if the wire is short-circuited with another wire or with any surface which might be present.
455455
+ `open` if the wire does not end in an ohmic contact with any other structure.
456-
+ Different configurations of passive circuit elements R, L, and C can be defined with `series` (for RLC series circuits), `LCpRs` (LC parallel in series with a resistance) and `RLsCp` (for series RL in parallel with C). The are defined as follows:
456+
+ Different configurations of passive circuit elements R, L, and C can be defined:
457+
+ `series` (for RLC series circuits),
458+
+ `parallel` (for RLC parallel circuits),
459+
+ `RsLCp` (LC parallel in series with R),
460+
+ `RLsCp` (RL series in parallel with C),
461+
+ `LsRCp` (RC parallel in series with L),
462+
+ `CsLRp` (LR parallel in parallel with C),
463+
+ `RCsLp` (RC series in parallel with L), and
464+
+ `LCsRp` (LC series in parallel with R).
465+
466+
The values are defined defined as follows:
457467
+ `[resistance]` which defaults to `0.0`,
458468
+ `[inductance]` which defaults to `0.0`,
459469
+ `[capacitance]` which defaults to `1e22`.
@@ -597,7 +607,9 @@ Records a vector field a single position referenced by `elementIds` which must c
597607

598608
Records a scalar field at a single position referenced by `elementIds`. `elementIds` must contain a single `id` referencing an element of type `node`. Additionally, this `node` must point to a `coordinateId` belonging to at least one `polyline`.
599609
If the node's `coordinateId` is shared by more than one `polyline` a probe will be defined for each one of them
600-
The `[field]` can be `voltage` or `current`. Defaults to `current`. When `current` is selected, the orientation of the `polyline` on which the probe is located indicates the direction of the current. Voltages are well defined at polyline points. However, currents are defined over segments so:
610+
The `[field]` can be `voltage`, `current` or `charge` (defaults to `current`). Voltage probes are properly defined only when used placed on `shieldedMultiwires`. The voltage on a conductor will be referred to the shield surrounding that conductor. In an unshielded wire, there is not a well defined reference, and thus the probe is not reliable. Charge probes are implemented only for wires not treated with the MTL module.
611+
612+
When `current` is selected, the orientation of the `polyline` on which the probe is located indicates the direction of the current. Voltages are well defined at polyline points. However, currents are defined over segments so:
601613

602614
- If the point is in the interior of the wire, the output will be an average on the currents of the segments which are contiguous to it.
603615
- If the point is at one wire end, the current will be the output of the last segment.
@@ -657,6 +669,19 @@ On the other hand, the coordinate **parallel** to the current also experiences a
657669

658670
Again, with the current flowing in the direction of the red line, the blue line represents a cross-sectional view of the plane where the `bulkCurrent` is defined, while the green line shows the actual location used for current evaluation by the method.
659671

672+
#### `line`
673+
674+
A `line` probe computes the electric field line integral along a given `polyline`. At low frequencies, this quantity can be equivalent to a DC voltage difference between the extremes of the line. At higher frequencies, "voltage" is no longer a proper name. The integral is performed along a geometric line, hence the `polyline` does not have to be associated with any material. `[field]` defaults to `electric`, the only field supported at this point. The probe is only valid in the time domain.
675+
676+
```json
677+
{
678+
"name" : "vprobe",
679+
"type" : "line",
680+
"elementIds" : [4],
681+
"field" : "electric"
682+
}
683+
```
684+
660685
#### `farField`
661686

662687
Probes of type `farField` perform a near to far field transformation of the electric and magnetic vector fields and are typically located in the scattered field region which is defined by a total/scatterd field excitation, e.g. [a planewave](#planewave).
@@ -771,8 +796,7 @@ This object represents a time-varying vector field applied along an oriented lin
771796
"type": "nodalSource",
772797
"magnitudeFile": "gauss.exc",
773798
"elementIds": [1],
774-
"hardness": "soft",
775-
"field": "electric"
799+
"hardness": "soft"
776800
}
777801
```
778802

19.3 KB
Loading
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import json
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
from pathlib import Path
5+
6+
def validate_json_structure(json_data):
7+
"""Validate the basic structure of the FDTD JSON file"""
8+
required_sections = ['format', 'general', 'boundary', 'materials',
9+
'mesh', 'probes', 'sources', 'materialAssociations']
10+
11+
for section in required_sections:
12+
if section not in json_data:
13+
print(f"Error: Missing required section '{section}'")
14+
return False
15+
return True
16+
17+
def validate_parameters(json_data):
18+
"""Validate specific parameters in the simulation"""
19+
# Check time step and number of steps
20+
time_step = json_data['general']['timeStep']
21+
num_steps = json_data['general']['numberOfSteps']
22+
total_time = time_step * num_steps
23+
24+
# Calculate expected propagation delay
25+
wire_length = 30 # meters (from mesh configuration)
26+
speed_of_light = 3e8 # m/s
27+
expected_delay = wire_length / speed_of_light
28+
29+
print(f"\nSimulation Parameters:")
30+
print(f"Time step: {time_step:.2e} s")
31+
print(f"Number of steps: {num_steps}")
32+
print(f"Total simulation time: {total_time:.2e} s")
33+
print(f"Expected propagation delay: {expected_delay:.2e} s")
34+
35+
if total_time < expected_delay:
36+
print(f"Warning: Total simulation time ({total_time:.2e} s) is less than expected propagation delay ({expected_delay:.2e} s)")
37+
return False
38+
return True
39+
40+
def visualize_circuit(json_data):
41+
"""Create a simple visualization of the circuit layout"""
42+
# Extract coordinates
43+
coords = json_data['mesh']['coordinates']
44+
elements = json_data['mesh']['elements']
45+
46+
# Create figure
47+
plt.figure(figsize=(12, 4))
48+
49+
# Plot wires
50+
for element in elements:
51+
if element['type'] == 'polyline':
52+
coord_ids = element['coordinateIds']
53+
x = [coords[coord_ids[0]-1]['relativePosition'][0],
54+
coords[coord_ids[1]-1]['relativePosition'][0]]
55+
z = [coords[coord_ids[0]-1]['relativePosition'][2],
56+
coords[coord_ids[1]-1]['relativePosition'][2]]
57+
plt.plot(z, x, 'b-', linewidth=2)
58+
59+
# Plot nodes
60+
for element in elements:
61+
if element['type'] == 'node':
62+
coord_id = element['coordinateIds'][0]
63+
pos = coords[coord_id-1]['relativePosition']
64+
plt.plot(pos[2], pos[0], 'ro', markersize=10)
65+
66+
plt.title('Circuit Layout')
67+
plt.xlabel('Z position (cells)')
68+
plt.ylabel('X position (cells)')
69+
plt.grid(True)
70+
plt.savefig('circuit_layout.png')
71+
plt.close()
72+
73+
def main():
74+
# Load JSON file
75+
json_path = Path(__file__).parent / 'closedCircuit.fdtd.json'
76+
try:
77+
with open(json_path, 'r') as f:
78+
json_data = json.load(f)
79+
except Exception as e:
80+
print(f"Error loading JSON file: {e}")
81+
return
82+
83+
print("Validating FDTD simulation file...")
84+
85+
# Validate structure
86+
if not validate_json_structure(json_data):
87+
print("JSON structure validation failed!")
88+
return
89+
90+
# Validate parameters
91+
if not validate_parameters(json_data):
92+
print("Parameter validation failed!")
93+
return
94+
95+
# Create visualization
96+
print("\nCreating circuit visualization...")
97+
visualize_circuit(json_data)
98+
print("Circuit layout saved as 'circuit_layout.png'")
99+
100+
print("\nValidation complete! The simulation file appears to be correctly configured.")
101+
print("You can now run the FDTD simulation.")
102+
103+
if __name__ == "__main__":
104+
main()
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
{
2+
"format": "FDTD Input file",
3+
"__comments": "Veritasium's circuit demonstration - The Big Misconception About Electricity",
4+
5+
"general": {
6+
"timeStep": 2.0e-9,
7+
"numberOfSteps": 100
8+
},
9+
10+
"boundary": {
11+
"all": {
12+
"type": "pml",
13+
"layers": 10,
14+
"order": 2.0,
15+
"reflection": 0.001
16+
}
17+
},
18+
19+
"mesh": {
20+
"grid": {
21+
"numberOfCells": [210, 300, 200],
22+
"steps": {"x": [0.1], "y": [0.1], "z": [0.1]}
23+
},
24+
25+
"coordinates": [
26+
{"id": 1, "relativePosition": [100, 149, 100]},
27+
{"id": 2, "relativePosition": [100, 100, 100]},
28+
{"id": 3, "relativePosition": [110, 100, 100]},
29+
{"id": 4, "relativePosition": [110, 150, 100]},
30+
{"id": 5, "relativePosition": [110, 200, 100]},
31+
{"id": 6, "relativePosition": [100, 200, 100]},
32+
{"id": 7, "relativePosition": [100, 151, 100]}
33+
],
34+
35+
"elements": [
36+
{"id": 1, "type": "polyline", "coordinateIds": [1, 2, 3, 4, 5, 6, 7]},
37+
{"id": 2, "type": "node", "coordinateIds": [4]},
38+
{"id": 3, "type": "cell", "name": "cube", "intervals": [ [ [99, 149, 99], [101, 151, 101] ] ]},
39+
{"id": 4, "type": "cell", "name": "wire-plane", "intervals": [ [ [105, 99, 99], [105, 101, 101] ] ]},
40+
{"id": 5, "type": "cell", "name": "source-plane", "intervals": [ [ [109, 150, 99], [111, 150, 101] ] ]},
41+
{"id": 6, "type": "cell", "name": "cube-plane", "intervals": [ [ [98, 150, 98], [102, 150, 102] ] ]},
42+
{"id": 7, "type": "cell", "name": "movie-domain", "intervals": [ [ [80, 80, 80], [130, 220, 120] ] ]}
43+
]
44+
},
45+
46+
"materials": [
47+
{
48+
"id": 1,
49+
"name": "wire_material",
50+
"type": "wire",
51+
"radius": 0.0001,
52+
"resistancePerMeter": 22.9e-3
53+
},
54+
{
55+
"id": 2,
56+
"name": "resistance_material",
57+
"type": "terminal",
58+
"terminations": [
59+
{"type": "series", "resistance": 50.0}
60+
]
61+
},
62+
{
63+
"id": 3,
64+
"name": "cube_material",
65+
"type": "pec"
66+
}
67+
],
68+
69+
"materialAssociations": [
70+
{
71+
"name": "wire_association",
72+
"elementIds": [1],
73+
"materialId": 1,
74+
"initialTerminalId": 2,
75+
"endTerminalId": 2
76+
},
77+
{
78+
"name": "cube_association",
79+
"elementIds": [3],
80+
"materialId": 3
81+
}
82+
],
83+
84+
"sources": [
85+
{
86+
"name": "source_generator",
87+
"type": "generator",
88+
"magnitudeFile": "step.exc",
89+
"elementIds": [2],
90+
"field": "voltage"
91+
}
92+
],
93+
94+
"probes": [
95+
{
96+
"name": "wire_current",
97+
"type": "bulkCurrent",
98+
"elementIds": [4]
99+
},
100+
{
101+
"name": "source_current",
102+
"type": "bulkCurrent",
103+
"elementIds": [5]
104+
},
105+
{
106+
"name": "cube_current",
107+
"type": "bulkCurrent",
108+
"elementIds": [6]
109+
},
110+
{
111+
"name": "movie_electric",
112+
"type": "movie",
113+
"field": "electric",
114+
"component": "magnitude",
115+
"elementIds": [7],
116+
"domain": {
117+
"initialTime": 0.0,
118+
"finalTime": 2e-7,
119+
"samplingPeriod": 1.5e-10
120+
}
121+
}
122+
]
123+
}

0 commit comments

Comments
 (0)