diff --git a/.github/workflows/run_tests_windows.bat b/.github/workflows/run_tests_windows.bat index b50453f2..0efa6dbe 100644 --- a/.github/workflows/run_tests_windows.bat +++ b/.github/workflows/run_tests_windows.bat @@ -19,5 +19,4 @@ IF "%VS_VER%"=="2017_build_tools" ( for /f "tokens=* usebackq" %%f in (`dir /b "C:\Program Files (x86)\Intel\oneAPI\compiler\" ^| findstr /V latest ^| sort`) do @set "LATEST_VERSION=%%f" @call "C:\Program Files (x86)\Intel\oneAPI\compiler\%LATEST_VERSION%\env\vars.bat" -build\bin\fdtd_tests.exe python -m pytest test \ No newline at end of file diff --git a/.github/workflows/windows-intelLLVM.yml b/.github/workflows/windows-intelLLVM.yml index a0e8a3f5..e90fe55d 100644 --- a/.github/workflows/windows-intelLLVM.yml +++ b/.github/workflows/windows-intelLLVM.yml @@ -46,8 +46,13 @@ jobs: run: | python -m pip install -r requirements.txt - - name: Run all tests + - name: Run unit tests shell: bash - timeout-minutes: 120 + timeout-minutes: 10 + run: build/bin/fdtd_tests.exe + + - name: Run system tests + shell: bash + timeout-minutes: 30 run: | .github/workflows/run_tests_windows.bat \ No newline at end of file diff --git a/doc/smbjson.md b/doc/smbjson.md index 54f8e103..d019a485 100644 --- a/doc/smbjson.md +++ b/doc/smbjson.md @@ -51,7 +51,7 @@ The following entries are shared by several FDTD-JSON objects and have a common + `type` followed by a string, indicates the type of JSON object that. Some examples of types are `planewave` for `sources` objects, and `polyline` for `elements`. + `id` is a unique integer identifier for objects that belong to a list and which can be referenced by other objects. For instance, an element in the `elements` list must contain a `id` which can be referenced by a source in `sources` through its list of `elementIds`. -+ `[name]` is an optional entry which is used to make the FDTD-JSON input human-readable, helping to identify inputs and outputs. ++ `[name]` is an optional entry which is used to make the FDTD-JSON input human-readable, helping to identify inputs and outputs. Leading and trailing blank spaces are removed. Blank spaces are substituted by underscroes. The following characters are reserved and can't be used in a `name`: `@`. ### `` @@ -85,12 +85,13 @@ These objects must contain a `` label which can be: + `pec` for perfectly electric conducting termination. + `pmc` for perfectly magnetic conducting termination. ++ `periodic` for periodic boundary conditions. Must be paired with the opposite side. + `mur` for Mur's first order absorbing boundary condition. + `pml` for perfectly matched layer termination. If this `type` is selected, it must also contain: - + `[layers]`: with an integer indicating the number of pml layers which will be used. TODO Change to an optional input which defaults to 10 layers - + `[order]`: TODO Change to an optional input which defaults to order 2. - + `[reflection]`: TODO Change to an optional input which defaults to 0.001 refl. + + `[layers]`: with an integer indicating the number of pml layers which will be used. Defaults to $10$ layers + + `[order]`: an integer indicating the order of the profile. defaults to order $2$. + + `[reflection]`: Computed reflection coefficient, defaults to $0.001$. **Example:** @@ -253,9 +254,9 @@ These materials represent a perfectly electrically conducting (`pec`) and perfec "materials": [ {"id": 1, "type": "pec"} ] ``` -#### `simple` +#### `isotropic` -A `material` with `type` `simple` represents an isotropic material with constant (not frequency dependent) relative permittivity $\varepsilon_r$, relative permeability $\mu_r$, electric conductivity $\sigma$ and/or magnetic conductivity $\sigma_m$: +A `material` with `type` `isotropic` represents an isotropic material with constant (not frequency dependent) relative permittivity $\varepsilon_r$, relative permeability $\mu_r$, electric conductivity $\sigma$ and/or magnetic conductivity $\sigma_m$: + `[relativePermittivity]` is a real which defaults to $1.0$. Must be greater than $1.0$. + `[relativePermeability]` is a real which defaults to $1.0$. Must be greater than $1.0$. @@ -268,7 +269,7 @@ A `material` with `type` `simple` represents an isotropic material with constant { "name": "teflon" "id": 1, - "type": "simple", + "type": "isotropic", "relativePermittivity": 2.5, "electricConducitivity": 1e-6 } @@ -280,7 +281,7 @@ In surface materials, `elementIds` must reference `cell` elements. All `interval #### `multilayeredSurface` -A `multilayeredSurface` must contain the entry `` which is an array indicating materials which are described in the same way as [simple materials](#simple) and a ``. +A `multilayeredSurface` must contain the entry `` which is an array indicating materials which are described in the same way as [isotropic materials](#isotropic) and a ``. ```json { @@ -289,22 +290,26 @@ A `multilayeredSurface` must contain the entry `` which is an array indi "id": 2, "layers": [ {"thickness": 1e-3, "relativePermittivity": 1.3, "electricConductivity": 2e-4}, - {"thickness": 5e-3, "relativePermittivity": 1.3} + {"thickness": 5e-3, "relativePermittivity": 1.3}, {"thickness": 1e-3, "relativePermittivity": 1.3, "electricConductivity": 2e-4} ] } ``` -#### `frequencyDependentSurface` +### Line materials -The entry `` is the path to a file containing the poles and residues which are used to model the surface impedance of the material. +In line materials, `elementIds` must reference `cell` elements. All `intervals` modeling entities different to lines are ignored. + +#### `thinSlot` + +A `thinSlot` represents a gap between two conductive surfaces. Therefore it must be located at a surface and be defined using line cell elements only. Its `` is a real number which defines the distance between the surfaces in meters. ```json { - "name": "carbon_fiber_model", - "type": "frequencyDependentSurface", - "id": 3, - "file": "cfc.dat" + "name": "3mm-gap", + "type": "thinSlot", + "id": 2, + "width": 3e-3 } ``` @@ -469,7 +474,7 @@ This entry stores associations between `materials` and `elements` using their re ### `bulk` -Bulk materials such as `pec`, `pmc` or `simple` can be assigned to one or many elements of type `cell`. If the `cell` contains `intervals` representing points, these will be ignored. +Bulk materials such as `pec`, `pmc` or `isotropic` can be assigned to one or many elements of type `cell`. If the `cell` contains `intervals` representing points, these will be ignored. ```json "materialAssociations": [ @@ -488,6 +493,16 @@ Surface materials can only be assigned to elements of type `cell`. If the `cell` ] ``` +### `line` + +Line materials can only be assigned to elements of type `cell`. If the `cell` contains `intervals` representing entities different to segments these will be ignored. + +```json +"materialAssociations": [ + {"type": "line", "materialId": 2, "elementIds": [4]} +] +``` + ### `cable` This object establishes the relationship between the physical models described in a `material` and parts of the geometry. Besides a `type`, `materialId` and `elementIds`; a `cable` can contain the following inputs: @@ -579,8 +594,6 @@ Performs a loop integral along on the contour of the surface reference in the `e Due to Ampere's law, the loop integral of the magnetic field is equal to the total electric current passing through the surfaces. `[field]`, can be `electric` or `magnetic`. Defaults to `electric`, which gives the total current passing through the surface. -TODO REVIEW DO BULK CURRENTS DO AVERAGES OF MAGNETIC FIELDS IN CELLS NEXT TO THE SELECTED? - In the following example `elementId` points an element describing a single oriented surface, therefore `direction` does not need to be stated explicitly. ```json @@ -602,8 +615,6 @@ In this example `elementId` points to a volume element, therefore `direction` mu } ``` -TODO EXAMPLE IMAGE - #### `farField` 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). @@ -649,7 +660,7 @@ An example follows: ### `[domain]` -If `domain` is not specified, it defaults to record from the beginning to the end of the simulation. +If `domain` is not specified, it defaults to a time domain recording from the beginning to the end of the simulation. The domain must specify a `` from the following ones: + `time`, means recording only in time domain. A probe with a `domain` of this `type` can contain the following entries: diff --git a/src_json_parser/idchildtable.F90 b/src_json_parser/idchildtable.F90 index 3372e88f..0aa9c029 100644 --- a/src_json_parser/idchildtable.F90 +++ b/src_json_parser/idchildtable.F90 @@ -11,7 +11,8 @@ module idchildtable_mod type(fhash_tbl_t) :: idToChilds contains procedure :: getId - procedure :: count + procedure :: totalSize + procedure :: checkId end type interface IdChildTable_t @@ -42,9 +43,17 @@ function ctor(core, root, path) result(res) end do end function - integer function count(this) + function totalSize(this) result(res) class(IdChildTable_t) :: this - call this%idToChilds%stats(num_items=count) + integer :: res + call this%idToChilds%stats(num_items=res) + end function + + function checkId(this, id) result(stat) + class(IdChildTable_t) :: this + integer, intent(in) :: id + integer :: stat + call this%idToChilds%check_key(key(id), stat) end function function getId(this, id) result(res) @@ -66,5 +75,6 @@ function getId(this, id) result(res) res = d end select end function + #endif end module diff --git a/src_json_parser/mesh.F90 b/src_json_parser/mesh.F90 index ca22073a..6213ef77 100644 --- a/src_json_parser/mesh.F90 +++ b/src_json_parser/mesh.F90 @@ -37,7 +37,8 @@ module mesh_mod contains procedure :: addCoordinate => mesh_addCoordinate procedure :: getCoordinate => mesh_getCoordinate - procedure :: checkId => mesh_checkId + procedure :: checkCoordinateId => mesh_checkCoordinateId + procedure :: checkElementId => mesh_checkElementId procedure :: addElement => mesh_addElement procedure :: addCellRegion => mesh_addCellRegion @@ -86,12 +87,20 @@ subroutine mesh_printCoordHashInfo(this) end subroutine - subroutine mesh_checkId(this, id, stat) + function mesh_checkCoordinateId(this, id) result(stat) class(mesh_t) :: this integer, intent(in) :: id - integer, intent(inout) :: stat + integer :: stat call this%coordinates%check_key(key(id), stat) - end subroutine + end function + + + function mesh_checkElementId(this, id) result(stat) + class(mesh_t) :: this + integer, intent(in) :: id + integer :: stat + call this%elements%check_key(key(id), stat) + end function subroutine mesh_addCoordinate(this, id, coordinate) class(mesh_t) :: this diff --git a/src_json_parser/nfdetypes_extension.F90 b/src_json_parser/nfdetypes_extension.F90 index e725bd4b..304f10d0 100644 --- a/src_json_parser/nfdetypes_extension.F90 +++ b/src_json_parser/nfdetypes_extension.F90 @@ -7,6 +7,8 @@ module NFDETypes_extension public interface operator(==) + module procedure Parseador_eq + module procedure NFDEGeneral_eq module procedure desplazamiento_eq @@ -106,7 +108,13 @@ subroutine initializeProblemDescription(pD) allocate(pD%pmcRegs%vols(0)) allocate(pD%DielRegs) + allocate(pD%DielRegs%lins(0)) + allocate(pD%DielRegs%surfs(0)) + allocate(pD%DielRegs%vols(0)) + allocate(pD%LossyThinSurfs) + allocate(pD%LossyThinSurfs%cs(0)) + allocate(pD%frqDepMats) allocate(pD%aniMats) ! @@ -140,6 +148,7 @@ subroutine initializeProblemDescription(pD) allocate(pD%sWires) allocate(pD%tSlots) + allocate(pD%tSlots%tg(0)) allocate(pD%mtln) allocate(pD%mtln%cables(0)) @@ -219,20 +228,22 @@ elemental logical function pecregions_eq(a, b) pecregions_eq = & (a%nVols == b%nVols) .and. & (a%nSurfs == b%nSurfs) .and. & - (a%nLins == b%nLins) .and. & - all(a%Lins == b%Lins) .and. & - all(a%Vols == b%Vols) .and. & - all(a%Surfs == b%Surfs) + (a%nLins_max == b%nLins_max) .and. & + (a%nVols_max == b%nVols_max) .and. & + (a%nSurfs_max == b%nSurfs_max) .and. & + (a%nLins == b%nLins) + pecregions_eq = pecregions_eq .and. all(a%Lins == b%Lins) + pecregions_eq = pecregions_eq .and. all(a%surfs == b%surfs) + pecregions_eq = pecregions_eq .and. all(a%vols == b%vols) end function pecregions_eq elemental logical function dielectric_eq(a, b) type(dielectric_t), intent(in) :: a, b + logical :: allAssociated dielectric_eq = & (a%n_C1P == b%n_C1P) .and. & (a%n_C2P == b%n_C2P) .and. & - all(a%C1P == b%C1P) .and. & - all(a%C2P == b%C2P) .and. & (a%sigma == b%sigma) .and. & (a%eps == b%eps) .and. & (a%mu == b%mu) .and. & @@ -255,6 +266,15 @@ elemental logical function dielectric_eq(a, b) (a%diodo .eqv. b%diodo) .and. & (a%plain .eqv. b%plain) .and. & (a%PMLbody .eqv. b%PMLbody) + + allAssociated = & + associated(a%C1P) .and. associated(b%C1P) .and. & + associated(a%C2P) .and. associated(b%C2P) + if (.not. allAssociated) then + dielectric_eq = .false. + return + end if + dielectric_eq = all(a%C1P == b%C1P) .and. all(a%C2P == b%C2P) end function dielectric_eq elemental logical function freqdepenmaterial_eq(a, b) @@ -379,6 +399,17 @@ end function anisotropicelements_eq elemental logical function dielectricregions_eq(a, b) type(DielectricRegions), intent(in) :: a, b + logical :: allAssociated + + allAssociated = & + associated(a%Lins) .and. associated(b%Lins) .and. & + associated(a%Surfs) .and. associated(b%Surfs) .and. & + associated(a%Vols) .and. associated(b%Vols) + if (.not. allAssociated) then + dielectricregions_eq = .false. + return + end if + dielectricregions_eq = & a%nVols == b%nVols .and. & a%nSurfs == b%nSurfs .and. & @@ -387,10 +418,11 @@ elemental logical function dielectricregions_eq(a, b) a%nSurfs_max == b%nSurfs_max .and. & a%nLins_max == b%nLins_max .and. & a%n_C1P_max == b%n_C1P_max .and. & - a%n_C2P_max == b%n_C2P_max .and. & - all(a%Vols == b%Vols) .and. & - all(a%Surfs == b%Surfs) .and. & - all(a%Lins == b%Lins) + a%n_C2P_max == b%n_C2P_max + + dielectricregions_eq = dielectricregions_eq .and. all(a%Lins == b%Lins) + dielectricregions_eq = dielectricregions_eq .and. all(a%surfs == b%surfs) + dielectricregions_eq = dielectricregions_eq .and. all(a%vols == b%vols) end function dielectricregions_eq elemental logical function LossyThinSurface_eq(a, b) @@ -525,8 +557,15 @@ end function SlantedWire_eq elemental logical function SlantedWires_eq(a, b) type(SlantedWires), intent(in) :: a, b - - SlantedWires_eq = all(a%sw == b%sw) .and. & + logical :: allAssociated + allAssociated = & + associated(a%sw) .and. associated(b%sw) + if (.not. allAssociated) then + SlantedWires_eq = .false. + return + end if + SlantedWires_eq = & + all(a%sw == b%sw) .and. & (a%n_sw == b%n_sw) .and. & (a%n_sw_max == b%n_sw_max) end function SlantedWires_eq @@ -545,8 +584,14 @@ end function ThinSlotComp_eq elemental logical function ThinSlot_eq(a, b) type(ThinSlot), intent(in) :: a, b - - ThinSlot_eq = all(a%tgc == b%tgc) .and. & + logical :: allAssociated + allAssociated = associated(a%tgc) .and. associated(b%tgc) + if (.not. allAssociated) then + ThinSlot_eq = .false. + return + end if + ThinSlot_eq = & + all(a%tgc == b%tgc) .and. & (a%width == b%width) .and. & (a%n_tgc == b%n_tgc) .and. & (a%n_tgc_max == b%n_tgc_max) @@ -554,6 +599,11 @@ end function ThinSlot_eq elemental logical function ThinSlots_eq(a, b) type(ThinSlots), intent(in) :: a, b + if (.not. associated(a%tg) .or. & + .not. associated(b%tg)) then + ThinSlots_eq = .false. + return + end if ThinSlots_eq = all(a%tg == b%tg) .and. & (a%n_tg == b%n_tg) .and. & @@ -773,28 +823,10 @@ elemental logical function abstractSonda_eq(a, b) result(res) res = .false. if (a%n_FarField /= b%n_FarField) return - ! if (a%n_Electric /= b%n_Electric) return - ! if (a%n_Magnetic /= b%n_Magnetic) return - ! if (a%n_NormalElectric /= b%n_NormalElectric) return - ! if (a%n_NormalMagnetic /= b%n_NormalMagnetic) return - ! if (a%n_SurfaceElectricCurrent /= b%n_SurfaceElectricCurrent) return - ! if (a%n_SurfaceMagneticCurrent /= b%n_SurfaceMagneticCurrent) return if (.not. associated(a%FarField) .or. .not. associated(b%FarField)) return - ! if (.not. associated(a%Electric) .or. .not. associated(b%Electric)) return - ! if (.not. associated(a%Magnetic) .or. .not. associated(b%Magnetic)) return - ! if (.not. associated(a%NormalElectric) .or. .not. associated(b%NormalElectric)) return - ! if (.not. associated(a%NormalMagnetic) .or. .not. associated(b%NormalMagnetic)) return - ! if (.not. associated(a%SurfaceElectricCurrent) .or. .not. associated(b%SurfaceElectricCurrent)) return - ! if (.not. associated(a%SurfaceMagneticCurrent) .or. .not. associated(b%SurfaceMagneticCurrent)) return if (any(.not. a%FarField == b%FarField)) return - ! if (any(.not. a%Electric == b%Electric)) return - ! if (any(.not. a%Magnetic == b%Magnetic)) return - ! if (any(.not. a%NormalElectric == b%NormalElectric)) return - ! if (any(.not. a%NormalMagnetic == b%NormalMagnetic)) return - ! if (any(.not. a%SurfaceElectricCurrent == b%SurfaceElectricCurrent)) return - ! if (any(.not. a%SurfaceMagneticCurrent == b%SurfaceMagneticCurrent)) return res = .true. end function abstractSonda_eq diff --git a/src_json_parser/parser_tools.F90 b/src_json_parser/parser_tools.F90 index 07709aa6..73551d90 100644 --- a/src_json_parser/parser_tools.F90 +++ b/src_json_parser/parser_tools.F90 @@ -61,16 +61,21 @@ function getIntervalsInCellRegions(cellRegions, cellType) result (intervals) end function - subroutine cellRegionsToCoords(res, cellRegions, cellType) - type(coords), dimension(:), pointer :: res - type(cell_region_t), dimension(:), intent(in) :: cellRegions + function cellRegionToCoords(cellRegion, cellType, tag) result(res) + type(cell_region_t), intent(in) :: cellRegion integer, intent(in), optional :: cellType + character (LEN=BUFSIZE), optional, intent(in) :: tag + type(coords), dimension(:), allocatable :: res + type(cell_interval_t), dimension(:), allocatable :: intervals type(coords), dimension(:), allocatable :: cs - intervals = getIntervalsInCellRegions(cellRegions, cellType) - cs = cellIntervalsToCoords(intervals) - allocate(res(size(cs))) + intervals = getIntervalsInCellRegions([cellRegion], cellType) + if (present(tag)) then + cs = cellIntervalsToCoords(intervals, tag) + else + cs = cellIntervalsToCoords(intervals) + endif res = cs end @@ -110,24 +115,30 @@ function coordsToScaledCoords(cs) result(res) end do end - subroutine cellRegionsToScaledCoords(res, cellRegions) + subroutine cellRegionsToScaledCoords(res, cellRegions, tag) type(coords_scaled), dimension(:), pointer :: res type(cell_region_t), dimension(:), intent(in) :: cellRegions type(cell_interval_t), dimension(:), allocatable :: intervals type(coords), dimension(:), allocatable :: cs type(coords_scaled), dimension(:), allocatable :: scaledCoords + character (LEN=BUFSIZE), optional, intent(in) :: tag intervals = getIntervalsInCellRegions(cellRegions, CELL_TYPE_LINEL) - cs = cellIntervalsToCoords(intervals) + if (present(tag)) then + cs = cellIntervalsToCoords(intervals, tag) + else + cs = cellIntervalsToCoords(intervals) + endif scaledCoords = coordsToScaledCoords(cs) allocate(res(size(scaledCoords))) res = scaledCoords end - function cellIntervalsToCoords(ivls) result(res) + function cellIntervalsToCoords(ivls, tag) result(res) type(coords), dimension(:), pointer :: res type(cell_interval_t), dimension(:), intent(in) :: ivls integer :: i + character (LEN=BUFSIZE), optional, intent(in) :: tag allocate(res(size(ivls))) do i = 1, size(ivls) @@ -135,7 +146,11 @@ function cellIntervalsToCoords(ivls) result(res) call convertInterval(res(i)%Xi, res(i)%Xe, ivls(i), DIR_X) call convertInterval(res(i)%Yi, res(i)%Ye, ivls(i), DIR_Y) call convertInterval(res(i)%Zi, res(i)%Ze, ivls(i), DIR_Z) - res(i)%tag = '' + if (present(tag)) then + res(i)%tag = tag + else + res(i)%tag = '' + end if end do contains subroutine convertInterval(xi, xe, interval, dir) diff --git a/src_json_parser/smbjson.F90 b/src_json_parser/smbjson.F90 index a9020438..bef3eb3c 100644 --- a/src_json_parser/smbjson.F90 +++ b/src_json_parser/smbjson.F90 @@ -17,7 +17,9 @@ module smbjson implicit none - integer, private, parameter :: MAX_LINE = 256 + integer, private, parameter :: MAX_LINE = BUFSIZE + character (len=*), parameter :: TAG_MATERIAL = 'material' + character (len=*), parameter :: TAG_LAYER = 'layer' type, public :: parser_t private @@ -26,43 +28,50 @@ module smbjson type(json_core), pointer :: core => null() type(json_value), pointer :: root => null() type(mesh_t) :: mesh - type(IdChildTable_t) :: matTable + type(IdChildTable_t) :: matTable, elementTable contains procedure :: readProblemDescription + procedure :: readMesh ! private - procedure :: readGeneral - procedure :: readGrid - procedure :: readMediaMatrix - procedure :: readPECRegions - procedure :: readPMCRegions - procedure :: readBoundary - procedure :: readPlanewaves - procedure :: readNodalSources - procedure :: readProbes - procedure :: readMoreProbes - procedure :: readBlockProbes - procedure :: readVolumicProbes - procedure :: readThinWires + procedure, private :: readGeneral + procedure, private :: readGrid + procedure, private :: readMediaMatrix + procedure, private :: readPECRegions + procedure, private :: readPMCRegions + procedure, private :: readDielectricRegions + procedure, private :: readLossyThinSurfaces + procedure, private :: readBoundary + procedure, private :: readPlanewaves + procedure, private :: readNodalSources + procedure, private :: readProbes + procedure, private :: readMoreProbes + procedure, private :: readBlockProbes + procedure, private :: readVolumicProbes + procedure, private :: readThinWires + procedure, private :: readThinSlots ! - procedure :: readMesh ! - procedure :: readMTLN + procedure, private :: readMTLN ! - procedure :: getLogicalAt - procedure :: getIntAt - procedure :: getIntsAt - procedure :: getRealAt - procedure :: getRealsAt - procedure :: getMatrixAt - procedure :: getStrAt - procedure :: existsAt - procedure :: getCellRegionsWithMaterialType - procedure :: getDomain - procedure :: jsonValueFilterByKeyValue - procedure :: jsonValueFilterByKeyValues - procedure :: getSingleVolumeInElementsIds + procedure, private :: getLogicalAt + procedure, private :: getIntAt + procedure, private :: getIntsAt + procedure, private :: getRealAt + procedure, private :: getRealsAt + procedure, private :: getMatrixAt + procedure, private :: getStrAt + procedure, private :: existsAt + procedure, private :: getDomain + procedure, private :: buildPECPMCRegions + procedure, private :: getMaterialAssociations + procedure, private :: parseMaterialAssociation + procedure, private :: matAssToCoords + procedure, private :: buildTagName + procedure, private :: jsonValueFilterByKeyValue + procedure, private :: jsonValueFilterByKeyValues + procedure, private :: getSingleVolumeInElementsIds end type interface parser_t module procedure parser_ctor @@ -78,14 +87,20 @@ module smbjson real :: multiplier end type + type, private :: materialAssociation_t + character(:), allocatable :: name + integer :: materialId + integer, dimension(:), allocatable :: elementIds + character(:), allocatable :: matAssType + end type type, private :: domain_t - real :: tstart, tstop, tstep - real :: fstart, fstop - integer :: fstep + real :: tstart = 0.0, tstop = 0.0, tstep = 0.0 + real :: fstart = 0.0, fstop = 0.0 + integer :: fstep = 0 character(len=:), allocatable :: filename - integer :: type1, type2 - logical :: isLogarithmicFrequencySpacing + integer :: type1 = NP_T1_PLAIN, type2 = NP_T2_TIME + logical :: isLogarithmicFrequencySpacing = .false. end type contains function parser_ctor(filename) result(res) @@ -118,6 +133,7 @@ function readProblemDescription(this) result (res) this%mesh = this%readMesh() this%matTable = IdChildTable_t(this%core, this%root, J_MATERIALS) + this%elementTable = IdChildTable_t(this%core, this%root, J_MESH//'.'//J_ELEMENTS) call initializeProblemDescription(res) @@ -130,6 +146,8 @@ function readProblemDescription(this) result (res) ! Materials res%pecRegs = this%readPECRegions() res%pmcRegs = this%readPMCRegions() + res%dielRegs = this%readDielectricRegions() + res%lossyThinSurfs = this%readLossyThinSurfaces() ! Sources res%plnSrc = this%readPlanewaves() @@ -143,13 +161,9 @@ function readProblemDescription(this) result (res) ! Thin elements res%tWires = this%readThinWires() + res%tSlots = this%readThinSlots() res%mtln = this%readMTLN(res%despl) - !! Cleanup - !call this%core%destroy() - !call this%jsonfile%destroy() - !nullify(this%root) - end function function readMesh(this) result(res) @@ -321,45 +335,86 @@ subroutine assignDes(path, dest, numberOfCells) function readBoundary(this) result (res) class(parser_t) :: this type(Frontera) :: res - character(kind=json_CK,len=:), allocatable :: boundaryTypeLabel - logical(LK) :: allLabelFound = .false. - real :: orden, refl - call this%core%get(this%root, J_BOUNDARY//'.'//J_BND_ALL//'.'//J_TYPE, boundaryTypeLabel, allLabelFound) - if (allLabelFound) then - res%tipoFrontera(:) = labelToBoundaryType(boundaryTypeLabel) - if (all(res%tipoFrontera == F_PML)) then - res%propiedadesPML(:) = readPMLProperties(J_BOUNDARY//"."//J_BND_ALL) - end if - return - else - ! TODO Check every bound. - write(error_unit,*) 'WIP: Boundaries of different types not implemented.' + character (len=:), allocatable :: bdrType + type(json_value), pointer :: bdrs + logical :: found + character(len=*), parameter :: errorMsgInit = "ERROR reading boundary: " + + call this%core%get(this%root, J_BOUNDARY, bdrs, found) + if (.not. found) then + write(error_unit, * ) errorMsgInit, J_BOUNDARY, " object not found." end if + + block + call this%core%get(bdrs, J_BND_ALL//'.'//J_TYPE, bdrType, found) + if (found) then + res%tipoFrontera(:) = labelToBoundaryType(bdrType) + if (all(res%tipoFrontera == F_PML)) then + res%propiedadesPML(:) = readPMLProperties(J_BOUNDARY//"."//J_BND_ALL) + end if + return + end if + end block + + block + character(len=*), dimension(6), parameter :: placeLabels = & + [J_BND_XL, J_BND_XU, J_BND_YL, J_BND_YU, J_BND_ZL, J_BND_ZU] + integer :: i, j + do i = 1, 6 + bdrType = this%getStrAt(bdrs, placeLabels(i)//"."//J_TYPE, found) + if (.not. found) then + write(error_unit, *) errorMsgInit, placeLabels(i), " or ", J_BND_ALL, " not found." + end if + j = labelToBoundaryPlace(placeLabels(i)) + res%tipoFrontera(j) = labelToBoundaryType(bdrType) + if (res%tipoFrontera(j) == F_PML) then + res%propiedadesPML(j) = readPMLProperties(J_BOUNDARY//"."//placeLabels(i)) + end if + end do + end block + contains function readPMLProperties(p) result(res) type(FronteraPML) :: res character(len=*), intent(in) :: p call this%core%get(this%root, p//'.'//J_BND_PML_LAYERS, res%numCapas, default=8) - call this%core%get(this%root, p//'.'//J_BND_PML_ORDER, orden, default=2.0) - call this%core%get(this%root, p//'.'//J_BND_PML_REFLECTION, refl, default=0.001) - res%orden = orden - res%refl = refl + call this%core%get(this%root, p//'.'//J_BND_PML_ORDER, res%orden, default=2.0) + call this%core%get(this%root, p//'.'//J_BND_PML_REFLECTION, res%refl, default=0.001) end function - function labelToBoundaryType(str) result (type) - character(len=:), allocatable :: str - integer :: type + function labelToBoundaryPlace(str) result (place) + character(len=*), intent(in) :: str + integer :: place + select case (str) + case (J_BND_XL) + place = F_XL + case (J_BND_XU) + place = F_XU + case (J_BND_YL) + place = F_YL + case (J_BND_YU) + place = F_YU + case (J_BND_ZL) + place = F_ZL + case (J_BND_ZU) + place = F_ZU + end select + end function + + function labelToBoundaryType(str) result (bdrType) + character(len=:), allocatable, intent(in) :: str + integer :: bdrType select case (str) case (J_BND_TYPE_PEC) - type = F_PEC + bdrType = F_PEC case (J_BND_TYPE_PMC) - type = F_PMC + bdrType = F_PMC case (J_BND_TYPE_PERIODIC) - type = F_PER + bdrType = F_PER case (J_BND_TYPE_MUR) - type = F_MUR + bdrType = F_MUR case (J_BND_TYPE_PML) - type = F_PML + bdrType = F_PML end select end function end function @@ -367,31 +422,308 @@ function labelToBoundaryType(str) result (type) function readPECRegions(this) result (res) class(parser_t), intent(in) :: this type(PECRegions) :: res - type(cell_region_t), dimension(:), allocatable :: cRs - cRs = this%getCellRegionsWithMaterialType(J_MAT_TYPE_PEC) - res = buildPECPMCRegion(cRs) + res = this%buildPECPMCRegions(J_MAT_TYPE_PEC) end function function readPMCRegions(this) result (res) class(parser_t), intent(in) :: this type(PECRegions) :: res - type(cell_region_t), dimension(:), allocatable :: cRs - cRs = this%getCellRegionsWithMaterialType(J_MAT_TYPE_PMC) - res = buildPECPMCRegion(cRs) + res = this%buildPECPMCRegions(J_MAT_TYPE_PMC) end function - function buildPECPMCRegion(cRs) result(res) + function buildPECPMCRegions(this, matType) result(res) + class(parser_t) :: this + character (len=*), intent(in) :: matType type(PECRegions) :: res - type(cell_region_t), dimension(:), allocatable, intent(in) :: cRs - call cellRegionsToCoords(res%Lins, cRs, CELL_TYPE_LINEL) - call cellRegionsToCoords(res%Surfs, cRs, CELL_TYPE_SURFEL) - call cellRegionsToCoords(res%Vols, cRs, CELL_TYPE_VOXEL) - res%nLins = size(res%lins) - res%nSurfs = size(res%surfs) + type(json_value_ptr), dimension(:), allocatable :: mAPtrs + type(materialAssociation_t) :: mA + type(coords), dimension(:), pointer :: cs + integer :: i + + mAPtrs = this%getMaterialAssociations(J_MAT_ASS_TYPE_BULK, matType) + + block + type(coords), dimension(:), pointer :: emptyCoords + if (size(mAPtrs) == 0) then + allocate(emptyCoords(0)) + call appendRegion(res%lins, res%nLins, res%nLins_max, emptyCoords) + call appendRegion(res%surfs, res%nSurfs, res%nSurfs_max, emptyCoords) + call appendRegion(res%vols, res%nVols, res%nVols_max, emptyCoords) + return + end if + end block + + do i = 1, size(mAPtrs) + mA = this%parseMaterialAssociation(mAptrs(i)%p) + call this%matAssToCoords(cs, mA, CELL_TYPE_LINEL) + call appendRegion(res%lins, res%nLins, res%nLins_max, cs) + call this%matAssToCoords(cs, mA, CELL_TYPE_SURFEL) + call appendRegion(res%surfs, res%nSurfs, res%nSurfs_max, cs) + call this%matAssToCoords(cs, mA, CELL_TYPE_VOXEL) + call appendRegion(res%vols, res%nVols, res%nVols_max, cs) + deallocate(cs) + end do + + contains + subroutine appendRegion(resCoords, resNCoords, resNCoordsMax, cs) + type(coords), dimension(:), pointer :: resCoords + integer, intent(out) :: resNCoords, resNCoordsMax + type(coords), dimension(:), pointer, intent(in) :: cs + type(coords) , dimension(:), allocatable :: auxCs + + if (.not. associated(resCoords)) then + allocate(resCoords(size(cs))) + resCoords(:) = cs(:) + resNCoords = size(cs) + resNCoordsMax = size(cs) + else + auxCs(:) = resCoords(:) + deallocate(resCoords) + allocate(resCoords(resNCoords + size(cs))) + resCoords(1:resNCoords) = auxCs + resCoords(resNCoords+1 : resNCoords+size(cs)) = cs(:) + resNCoords = resNCoords + size(cs) + resNCoordsMax = resNCoordsMax + size(cs) + end if + end subroutine + end function + + function readDielectricRegions(this) result (res) + class(parser_t), intent(in) :: this + type(DielectricRegions) :: res + type(json_value_ptr), dimension(:), allocatable :: matAssPtrs + + call fillDielectricsOfCellType(res%vols, CELL_TYPE_VOXEL) + call fillDielectricsOfCellType(res%surfs, CELL_TYPE_SURFEL) + call fillDielectricsOfCellType(res%lins, CELL_TYPE_LINEL) + res%nVols = size(res%vols) - res%nLins_max = size(res%Lins) - res%nSurfs_max = size(res%Surfs) - res%nVols_max = size(res%Vols) + res%nSurfs = size(res%Surfs) + res%nLins = size(res%Lins) + + res%nVols_max = res%nVols + res%nSurfs_max = res%nSurfs + res%nLins_max = res%nLins + contains + subroutine fillDielectricsOfCellType(res, cellType) + integer, intent(in) :: cellType + type(dielectric_t), dimension(:), pointer :: res + + type(json_value_ptr), dimension(:), allocatable :: mAPtrs + type(materialAssociation_t) :: mA + type(cell_region_t) :: cR + + integer :: i, j + integer :: nCs, nDielectrics + + mAPtrs = this%getMaterialAssociations(J_MAT_ASS_TYPE_BULK, J_MAT_TYPE_ISOTROPIC) + if (size(mAPtrs) == 0) then + allocate(res(0)) + return + end if + + ! Precounts + nDielectrics = 0 + do i = 1, size(mAPtrs) + if (containsCellRegionsWithType(mAPtrs(i)%p, cellType)) then + nDielectrics = nDielectrics + 1 + end if + end do + + ! Fills + allocate(res(nDielectrics)) + + if (nDielectrics == 0) return + + j = 0 + do i = 1, size(mAPtrs) + if (.not. containsCellRegionsWithType(mAPtrs(i)%p, cellType)) cycle + j = j + 1 + res(j) = readDielectric(mAPtrs(i)%p, cellType) + end do + end subroutine + + function readDielectric(mAPtr, cellType) result(res) + type(json_value), pointer, intent(in) :: mAPtr + integer, intent(in) :: cellType + type(Dielectric_t) :: res + type(materialAssociation_t) :: mA + type(cell_region_t) :: cR + type (coords), dimension(:), allocatable :: coords + + integer :: e, j + + mA = this%parseMaterialAssociation(mAPtr) + allocate(res%c1P(0)) + res%n_c1p = 0 + call this%matAssToCoords(res%c2p, mA, cellType) + res%n_c2p = size(res%c2p) + + ! Fills rest of dielectric data. + res%sigma = this%getRealAt(mAPtr, J_MAT_ELECTRIC_CONDUCTIVITY, default=0.0) + res%sigmam = this%getRealAt(mAPtr, J_MAT_MAGNETIC_CONDUCTIVITY, default=0.0) + res%eps = this%getRealAt(mAPtr, J_MAT_REL_PERMITTIVITY, default=1.0)*EPSILON_VACUUM + res%mu = this%getRealAt(mAPtr, J_MAT_REL_PERMEABILITY, default=1.0)*MU_VACUUM + + end function + + logical function containsCellRegionsWithType(mAPtr, cellType) + integer, intent(in) :: cellType + type(json_value), pointer, intent(in) :: mAPtr + type(materialAssociation_t) :: mA + integer :: e + type(cell_region_t) :: cR + + mA = this%parseMaterialAssociation(mAPtr) + do e = 1, size(mA%elementIds) + cR = this%mesh%getCellRegion(mA%elementIds(e)) + if (size(cellRegionToCoords(cR, cellType)) /= 0) then + containsCellRegionsWithType = .true. + return + end if + end do + + containsCellRegionsWithType = .false. + end function + end function + + subroutine matAssToCoords(this, res, mA, cellType) + class(parser_t) :: this + type(materialAssociation_t), intent(in) :: mA + type (coords), dimension(:), pointer :: res + integer, intent(in) :: cellType + character (len=:), allocatable :: tagName + type (coords), dimension(:), allocatable :: newCoords + type (cell_region_t) :: cR + integer :: nCs + integer :: e, jIni, jEnd + + ! Precount + nCs = 0 + do e = 1, size(mA%elementIds) + cR = this%mesh%getCellRegion(mA%elementIds(e)) + nCs = nCs + size(cellRegionToCoords(cR, cellType)) + end do + + ! Fills coords + jIni = 1 + allocate(res(nCs)) + do e = 1, size(mA%elementIds) + cR = this%mesh%getCellRegion(mA%elementIds(e)) + tagName = this%buildTagName(mA%materialId, mA%elementIds(e)) + newCoords = cellRegionToCoords(cR, cellType, tag=tagName) + if (size(newCoords) == 0) cycle + jEnd = jIni + size(newCoords) - 1 + res(jIni:jEnd) = newCoords(:) + jIni = jEnd + 1 + end do + end subroutine + + function readLossyThinSurfaces(this) result (res) + class(parser_t), intent(in) :: this + type(LossyThinSurfaces) :: res + type(json_value_ptr), dimension(:), allocatable :: matAssPtrs + type(json_value_ptr) :: mat + integer :: nLossySurfaces + logical :: found + integer :: i, j, k + type(materialAssociation_t) :: mA + + matAssPtrs = this%getMaterialAssociations(& + J_MAT_ASS_TYPE_SURFACE, J_MAT_TYPE_MULTILAYERED_SURFACE) + + ! Precounts + nLossySurfaces = 0 + do i = 1, size(matAssPtrs) + mA = this%parseMaterialAssociation(matAssPtrs(i)%p) + nLossySurfaces = nLossySurfaces + size(mA%elementIds) + end do + + ! Fills + if (nLossySurfaces == 0) then + res = emptyLossyThinSurfaces() + return + end if + + allocate(res%cs(nLossySurfaces)) + res%length = nLossySurfaces + res%length_max = nLossySurfaces + res%nC_max = nLossySurfaces + k = 1 + do i = 1, size(matAssPtrs) + mA = this%parseMaterialAssociation(matAssPtrs(i)%p) + do j = 1, size(mA%elementIds) + res%cs(k) = readLossyThinSurface(mA%materialId, mA%elementIds(j)) + k = k + 1 + end do + end do + + contains + function readLossyThinSurface(matId, eId) result(res) + integer, intent(in) :: matId + integer, intent(in) :: eId + type(LossyThinSurface) :: res + logical :: found + character (len=*), parameter :: errorMsgInit = "ERROR reading lossy thin surface: " + type(coords), dimension(:), allocatable :: cs + ! Reads coordinates. + res%nc = 1 + cs = cellRegionToCoords(this%mesh%getCellRegion(eId), & + tag = this%buildTagName(matId, eId)) + allocate(res%c(size(cs))) + res%c = cs(:) + + + ! Reads layers. + block + integer :: i + type(json_value_ptr) :: mat + type(json_value), pointer :: layer + type(json_value), pointer :: layers + + mat = this%matTable%getId(matId) + call this%core%get(mat%p, J_MAT_MULTILAYERED_SURF_LAYERS, layers, found) + if (.not. found) then + write(error_unit, *) errorMsgInit, J_MAT_MULTILAYERED_SURF_LAYERS, " not found." + end if + + res%numcapas = this%core%count(layers) + allocate(res%sigma( res%numcapas)) + allocate(res%eps( res%numcapas)) + allocate(res%mu( res%numcapas)) + allocate(res%sigmam(res%numcapas)) + allocate(res%thk( res%numcapas)) + allocate(res%sigma_devia( res%numcapas)) + allocate(res%eps_devia( res%numcapas)) + allocate(res%mu_devia( res%numcapas)) + allocate(res%sigmam_devia(res%numcapas)) + allocate(res%thk_devia( res%numcapas)) + do i = 1, res%numcapas + call this%core%get_child(layers, i, layer) + res%sigma(i) = this%getRealAt(layer, J_MAT_ELECTRIC_CONDUCTIVITY, default=0.0) + res%sigmam(i) = this%getRealAt(layer, J_MAT_MAGNETIC_CONDUCTIVITY, default=0.0) + res%eps(i) = this%getRealAt(layer, J_MAT_REL_PERMITTIVITY, default=1.0) * EPSILON_VACUUM + res%mu(i) = this%getRealAt(layer, J_MAT_REL_PERMEABILITY, default=1.0) * MU_VACUUM + res%thk(i) = this%getRealAt(layer, J_MAT_MULTILAYERED_SURF_THICKNESS, found) + res%sigma_devia(i) = 0.0 + res%eps_devia(i) = 0.0 + res%mu_devia(i) = 0.0 + res%sigmam_devia(i) = 0.0 + res%thk_devia(i) = 0.0 + if (.not. found) then + write(error_unit, *) errorMsgInit, J_MAT_MULTILAYERED_SURF_THICKNESS, " in layer not found." + end if + end do + end block + end function + + function emptyLossyThinSurfaces() result (res) + type(LossyThinSurfaces) :: res + allocate(res%cs(0)) + res%length = 0 + res%length_max = 0 + res%nC_max = 0 + end function end function function readPlanewaves(this) result (res) @@ -428,8 +760,7 @@ function readPlanewave(pw) result (res) character (len=:), allocatable :: label logical :: found - res%nombre_fichero = trim(adjustl( & - this%getStrAt(pw,J_SRC_MAGNITUDE_FILE))) + res%nombre_fichero = trim(adjustl(this%getStrAt(pw,J_SRC_MAGNITUDE_FILE))) call this%core%get(pw, J_SRC_PW_ATTRIBUTE, label, found) if (found) then @@ -686,7 +1017,7 @@ function readMoreProbes(this) result (res) do i=1, size(ps) call this%core%get(ps(i)%p, J_FIELD, fieldLbl) if (fieldLbl /= J_FIELD_VOLTAGE) then - res%collection(n) = readProbe(ps(i)%p) + res%collection(n) = readPointProbe(ps(i)%p) n = n + 1 end if end do @@ -695,9 +1026,10 @@ function readMoreProbes(this) result (res) res%length_max = size(res%collection) res%len_cor_max = 0 contains - function readProbe(p) result (res) + function readPointProbe(p) result (res) type(MasSonda) :: res - type(json_value), pointer :: p, dirLabels, dirLabelPtr + type(json_value), pointer :: p, dirLabelPtr + character(len=1), dimension(:), allocatable :: dirLabels integer :: i, j, k character (len=:), allocatable :: typeLabel, fieldLabel, outputName, dirLabel type(pixel_t) :: pixel @@ -710,6 +1042,7 @@ function readProbe(p) result (res) write(error_unit, *) "ERROR: name entry not found for probe." end if res%outputrequest = trim(adjustl(outputName)) + call setDomain(res, this%getDomain(p, J_PR_DOMAIN)) call this%core%get(p, J_ELEMENTIDS, elemIds, found=elementIdsFound) @@ -736,47 +1069,43 @@ function readProbe(p) result (res) res%cordinates(1)%Zi = 0 res%cordinates(1)%Or = strToFieldType(fieldLabel) case (J_PR_TYPE_POINT) - call this%core%get(p, J_PR_POINT_DIRECTIONS, dirLabels, found=dirLabelsFound) - if (.not. dirLabelsFound) then - write(error_unit, *) "ERROR: Point probe direction labels not found." + call this%core%get(p, J_PR_POINT_DIRECTIONS, dirLabelPtr, found=dirLabelsFound) + if(dirLabelsFound) then + dirLabels = buildDirLabels(dirLabelPtr) + else + dirLabels = [J_DIR_X, J_DIR_Y, J_DIR_Z] end if call this%core%get(p, J_FIELD, fieldLabel, default=J_FIELD_ELECTRIC, found=fieldLabelFound) if (.not. fieldLabelFound) then write(error_unit, *) "ERROR: Point probe field label not found." - end if - if (dirLabelsFound) then - allocate(res%cordinates(this%core%count(dirLabels))) - do j = 1, this%core%count(dirLabels) - res%cordinates(j)%tag = outputName - res%cordinates(j)%Xi = int (pixel%cell(1)) - res%cordinates(j)%Yi = int (pixel%cell(2)) - res%cordinates(j)%Zi = int (pixel%cell(3)) - call this%core%get_child(dirLabels, j, dirLabelPtr) - call this%core%get(dirLabelPtr, dirLabel) - res%cordinates(j)%Or = strToFieldType(fieldLabel, dirLabel) - end do - else - do j = 1, 3 - res%cordinates(j)%tag = outputName - res%cordinates(j)%Xi = int (pixel%cell(1)) - res%cordinates(j)%Yi = int (pixel%cell(2)) - res%cordinates(j)%Zi = int (pixel%cell(3)) - select case (j) - case (1) - dirLabel = J_DIR_X - case (2) - dirLabel = J_DIR_Y - case (3) - dirLabel = J_DIR_Z - end select - res%cordinates(j)%Or = strToFieldType(fieldLabel, dirLabel) - end do - end if + end if + allocate(res%cordinates(size(dirLabels))) + do j = 1, size(dirLabels) + res%cordinates(j)%tag = outputName + res%cordinates(j)%Xi = int (pixel%cell(1)) + res%cordinates(j)%Yi = int (pixel%cell(2)) + res%cordinates(j)%Zi = int (pixel%cell(3)) + res%cordinates(j)%Or = strToFieldType(fieldLabel, dirLabels(j)) + end do end select res%len_cor = size(res%cordinates) end function + function buildDirLabels(dirLabelsPtr) result (res) + type(json_value), pointer, intent(in) :: dirLabelsPtr + character(len=1), dimension(:), allocatable :: res + type(json_value), pointer :: child + character(len=:), allocatable :: str + integer :: i + allocate(res(this%core%count(dirLabelsPtr))) + do i = 1, this%core%count(dirLabelsPtr) + call this%core%get_child(dirLabelsPtr, i, child) + call this%core%get(child, str) + res(i) = str + end do + end function + subroutine setDomain(res, domain) type(MasSonda), intent(inout) :: res type(domain_t), intent(in) :: domain @@ -1055,6 +1384,101 @@ subroutine appendLogSufix(fn) fn = trim(fn) // SMBJSON_LOG_SUFFIX end subroutine + function readThinSlots(this) result (res) + class(parser_t) :: this + type(ThinSlots) :: res + + type(json_value_ptr), dimension(:), allocatable :: mAPtrs + integer :: i + + mAPtrs = this%getMaterialAssociations(J_MAT_ASS_TYPE_LINE, J_MAT_TYPE_SLOT) + if (size(mAPtrs) == 0) then + allocate(res%tg(0)) + return + end if + + res%n_tg = size(mAPtrs) + allocate(res%tg(res%n_tg)) + do i = 1, size(mAPtrs) + res%tg = readThinSlot(mAPtrs(i)%p) + end do + contains + function readThinSlot(mAPtr) result(res) + type (json_value), pointer, intent(in) :: mAPtr + type (thinSlot) :: res + type (materialAssociation_t) :: mA + type (coords), dimension(:), pointer :: cs + type(json_value_ptr) :: mat + logical :: found + + mA = this%parseMaterialAssociation(mAPtr) + + mat = this%matTable%getId(mA%materialId) + res%width = this%getRealAt(mat%p, J_MAT_THINSLOT_WIDTH, found) + if (.not. found) then + write(error_unit, *) "ERROR reading thin slot: ", & + J_MAT_THINSLOT_WIDTH, "not found" + end if + + call this%matAssToCoords(cs, mA, CELL_TYPE_LINEL) + call coordsToThinSlotComp(res%tgc, cs) + res%n_tgc = size(res%tgc) + + end function + + subroutine coordsToThinSlotComp(tc, cs) + type(coords), dimension(:), pointer, intent(in) :: cs + type(thinSlotComp), dimension(:), pointer :: tc + integer :: i, j, k + integer :: nTgc, nXYZ + integer :: dir + ! Precount + nTgc = 0 + do i = 1, size(cs) + nXYZ = (cs(i)%xe - cs(i)%xi + 1) * & + (cs(i)%ye - cs(i)%yi + 1) * & + (cs(i)%ze - cs(i)%zi + 1) + nTgc = nTgc + nXYZ + end do + + ! Fill + j = 1 + allocate(tc(nTgc)) + do i = 1, size(cs) + select case (abs(cs(i)%Or)) + case (iEx) + do k = 1, (cs(i)%xe - cs(i)%xi + 1) + tc(j) = buildBaseThinSlotComponent(cs(i)) + tc(j)%i = cs(i)%xi + k - 1 + j = j + 1 + end do + case (iEy) + do k = 1, (cs(i)%xe - cs(i)%xi + 1) + tc(j) = buildBaseThinSlotComponent(cs(i)) + tc(j)%j = cs(i)%yi + k - 1 + j = j + 1 + end do + case (iEz) + do k = 1, (cs(i)%xe - cs(i)%xi + 1) + tc(j) = buildBaseThinSlotComponent(cs(i)) + tc(j)%k = cs(i)%zi + k - 1 + j = j + 1 + end do + end select + end do + end subroutine + + function buildBaseThinSlotComponent(cs) result(res) + type(coords), intent(in) :: cs + type(thinSlotComp) :: res + res%i = cs%xi + res%j = cs%yi + res%k = cs%zi + res%dir = abs(cs%Or) + res%tag = cs%tag + end function + end function + function readThinWires(this) result (res) class(parser_t) :: this type(ThinWires) :: res @@ -1362,8 +1786,10 @@ function getDomain(this, place, path) result(res) real :: val call this%core%get(place, path, domain, found) - if (.not. found) return - + if (.not. found) then + res%filename = " " + return + end if call this%core%get(domain, J_PR_DOMAIN_MAGNITUDE_FILE, fn, transferFunctionFound) if (found) then @@ -1444,6 +1870,170 @@ function getNPDomainType(typeLabel, hasTransferFunction) result(res) end function end function + function parseMaterialAssociation(this, matAss) result(res) + class(parser_t) :: this + type(json_value), pointer, intent(in) :: matAss + type(materialAssociation_t) :: res + character (len=*), parameter :: errorMsgInit = "ERROR reading material association: " + logical :: found + + ! Fills material association. + res%materialId = this%getIntAt(matAss, J_MATERIAL_ID, found) + if (.not. found) call showLabelNotFoundError(J_MATERIAL_ID) + res%elementIds = this%getIntsAt(matAss, J_ELEMENTIDS, found) + if (.not. found) call showLabelNotFoundError(J_ELEMENTIDS) + res%matAssType = this%getStrAt(matAss, J_TYPE, found) + if (.not. found) call showLabelNotFoundError(J_TYPE) + res%name = this%getStrAt(matAss, J_NAME, found) + if (.not. found) then + res%name = "" + end if + + ! Checks validity of associations. + if (this%matTable%checkId(res%materialId) /= 0) then + write(error_unit, *) errorMsgInit, "material with id ", res%materialId, " not found." + endif + + if (size(res%elementIds) == 0) then + write(error_unit, *) errorMsgInit, J_ELEMENTIDS, "must not be empty." + end if + block + integer :: i + do i = 1, size(res%elementIds) + if (this%mesh%checkElementId(res%elementIds(i)) /= 0) then + write(error_unit, *) errorMsgInit, "element with id ", res%elementIds(i), " not found." + end if + end do + end block + + ! This function does not work with material associations for cables. + ! DO NOT use it to read that. + if (res%matAssType == J_MAT_ASS_TYPE_CABLE) then + write(error_unit, *) errorMsgInit, "invalid type." + endif + + contains + subroutine showLabelNotFoundError(label) + character (len=*), intent(in) :: label + + end subroutine + end function + + function getMaterialAssociations(this, matAssType, materialType) result(res) + class(parser_t) :: this + type(json_value), pointer :: allMatAss + character(len=*), intent(in) :: matAssType + character(len=*), intent(in) :: materialType + type(json_value_ptr), dimension(:), allocatable :: res + + type(json_value_ptr), dimension(:), allocatable :: mAPtrs + integer :: i, j + integer :: nMaterials + logical :: found + + call this%core%get(this%root, J_MATERIAL_ASSOCIATIONS, allMatAss, found) + if (.not. found) then + allocate(res(0)) + return + end if + + mAPtrs = this%jsonValueFilterByKeyValue(allMatAss, J_TYPE, matAssType) + if (size(mAPtrs) == 0) then + allocate(res(0)) + return + end if + + + nMaterials = 0 + do i = 1, size(mAPtrs) + if (isAssociatedWithMaterial(mAPtrs(i)%p, materialType)) then + nMaterials = nMaterials + 1 + end if + end do + + allocate(res(nMaterials)) + j = 1 + do i = 1, size(mAPtrs) + if (isAssociatedWithMaterial(mAPtrs(i)%p, materialType)) then + res(j) = mAPtrs(i) + j = j+1 + end if + end do + + contains + logical function isAssociatedWithMaterial(mAPtr, materialType) + type(json_value), pointer, intent(in) :: mAPtr + character (len=*), intent(in) :: materialType + + type(materialAssociation_t) :: matAss + type(json_value_ptr) :: mat + + matAss = this%parseMaterialAssociation(mAPtr) + mat = this%matTable%getId(matAss%materialId) + isAssociatedWithMaterial = this%getStrAt(mat%p, J_TYPE) == materialType + end function + end function + + function buildTagName(this, matId, elementId) result(res) + class(parser_t) :: this + integer, intent(in) :: matId, elementId + character(len=BUFSIZE) :: res + character(len=:), allocatable :: matName, layerName + logical :: found + + block + type(json_value_ptr) :: mat + mat = this%matTable%getId(matId) + matName = this%getStrAt(mat%p, J_NAME, found) + if (.not. found) then + deallocate(matName) + allocate(character(len(TAG_MATERIAL) + 12) :: matName) + write(matName, '(a,i0)') TAG_MATERIAL, matId + end if + matName = adaptName(matName) + end block + + block + type(json_value_ptr) :: elem + elem = this%elementTable%getId(elementId) + layerName = this%getStrAt(elem%p, J_NAME, found) + if (.not. found) then + deallocate(layerName) + allocate(character(len(TAG_LAYER) + 12) :: layerName) + write(layerName, '(a,i0)') TAG_LAYER, elementId + end if + layerName = adaptName(layerName) + end block + + call checkIsValidName(matName) + call checkIsValidName(layerName) + res = trim(matName // '@' // layerName) + contains + subroutine checkIsValidName(str) + character (len=:), allocatable, intent(in) :: str + character (len=*), parameter :: notAllowedChars = '@' + integer :: i + do i = 1, len((notAllowedChars)) + if (index(str, notAllowedChars(i:i)) /= 0) then + write(error_unit, *) "ERROR in name: ", str, & + " contains invalid character ", notAllowedChars(i:i) + end if + end do + end subroutine + + function adaptName(str) result(res) + character (len=:), allocatable, intent(in) :: str + character (len=:), allocatable :: res + integer :: i + res = trim(adjustl(str)) + do i = 1, len(res) + if (res(i:i) == ' ') then + res(i:i) = '_' + end if + end do + end function + end function + function readMTLN(this, grid) result (mtln_res) class(parser_t) :: this type(Desplazamiento), intent(in) :: grid @@ -2699,13 +3289,14 @@ function getIntsAt(this, place, path, found) result(res) call this%core%get(place, path, res, found) end function - function getRealAt(this, place, path, found) result(res) + function getRealAt(this, place, path, found, default) result(res) real :: res class(parser_t) :: this type(json_value), pointer :: place character(len=*) :: path logical, intent(out), optional :: found - call this%core%get(place, path, res, found) + real, optional :: default + call this%core%get(place, path, res, found, default) end function function getRealsAt(this, place, path, found) result(res) @@ -2757,43 +3348,6 @@ function existsAt(this, place, path) result(res) call this%core%info(place, path, found=res) end function - function getCellRegionsWithMaterialType(this, matType) result(res) - class(parser_t) :: this - character (len=*), intent(in) :: matType - type(cell_region_t), dimension(:), allocatable :: res - - logical :: found - type(json_value), pointer :: jmrs, jmr - type(json_value_ptr) :: jm - integer, dimension(:), allocatable :: eIds - type(cell_region_t) :: cR - integer :: i, j - integer :: numCellRegions - - call this%core%get(this%root, J_MATERIAL_ASSOCIATIONS, jmrs, found) - allocate(res(0)) - if (.not. found) then - return - end if - - do i = 1, this%core%count(jmrs) - call this%core%get_child(jmrs, i, jmr) - jm = this%matTable%getId(this%getIntAt(jmr, J_MATERIAL_ID, found)) - if (.not. found) & - write(error_unit, *) "Error reading material region: materialId label not found." - - if (matType == this%getStrAt(jm%p, J_TYPE)) then - eIds = this%getIntsAt(jmr, J_ELEMENTIDS) - do j = 1, size(eIds) - cR = this%mesh%getCellRegion(eIds(j), found) - if (found) then - res = [res, cR] - end if - end do - end if - end do - end function - function jsonValueFilterByKeyValues(this, srcs, key, values) result (res) class(parser_t) :: this type(json_value_ptr), dimension(:), allocatable :: res diff --git a/src_json_parser/smbjson_labels.F90 b/src_json_parser/smbjson_labels.F90 index c56001ac..a8d2aeed 100644 --- a/src_json_parser/smbjson_labels.F90 +++ b/src_json_parser/smbjson_labels.F90 @@ -22,10 +22,16 @@ module smbjson_labels_mod ! -- materials character (len=*), parameter :: J_MATERIALS = "materials" + character (len=*), parameter :: J_MAT_REL_PERMITTIVITY = "relativePermittivity" + character (len=*), parameter :: J_MAT_REL_PERMEABILITY = "relativePermeability" + character (len=*), parameter :: J_MAT_ELECTRIC_CONDUCTIVITY = "electricConductivity" + character (len=*), parameter :: J_MAT_MAGNETIC_CONDUCTIVITY = "magneticConductivity" character (len=*), parameter :: J_MAT_TYPE_PEC = "pec" character (len=*), parameter :: J_MAT_TYPE_PMC = "pmc" - character (len=*), parameter :: J_MAT_TYPE_SIMPLE = "simple" + character (len=*), parameter :: J_MAT_TYPE_ISOTROPIC = "isotropic" + character (len=*), parameter :: J_MAT_TYPE_MULTILAYERED_SURFACE = "multilayeredSurface" + character (len=*), parameter :: J_MAT_TYPE_SLOT = "thinSlot" character (len=*), parameter :: J_MAT_TYPE_WIRE = "wire" character (len=*), parameter :: J_MAT_TYPE_MULTIWIRE = "multiwire" character (len=*), parameter :: J_MAT_TYPE_TERMINAL = "terminal" @@ -59,12 +65,18 @@ module smbjson_labels_mod character (len=*), parameter :: J_MAT_MULTIWIRE_RESISTANCE = "resistancePerMeter" character (len=*), parameter :: J_MAT_MULTIWIRE_CONDUCTANCE = "conductancePerMeter" + character (len=*), parameter :: J_MAT_MULTILAYERED_SURF_LAYERS = "layers" + character (len=*), parameter :: J_MAT_MULTILAYERED_SURF_THICKNESS = "thickness" + + character (len=*), parameter :: J_MAT_THINSLOT_WIDTH = "width" + ! -- materialAssociations character (len=*), parameter :: J_MATERIAL_ASSOCIATIONS = "materialAssociations" character (len=*), parameter :: J_MATERIAL_ID = "materialId" character (len=*), parameter :: J_MAT_ASS_TYPE_BULK = "bulk" character (len=*), parameter :: J_MAT_ASS_TYPE_SURFACE = "surface" + character (len=*), parameter :: J_MAT_ASS_TYPE_LINE = "line" character (len=*), parameter :: J_MAT_ASS_TYPE_CABLE = "cable" character (len=*), parameter :: J_MAT_ASS_CAB_INI_TERM_ID = "initialTerminalId" @@ -119,6 +131,13 @@ module smbjson_labels_mod ! type(Frontera) character (len=*), parameter :: J_BOUNDARY = "boundary" character (len=*), parameter :: J_BND_ALL = "all" + character (len=*), parameter :: J_BND_XL = "xLower" + character (len=*), parameter :: J_BND_XU = "xUpper" + character (len=*), parameter :: J_BND_YL = "yLower" + character (len=*), parameter :: J_BND_YU = "yUpper" + character (len=*), parameter :: J_BND_ZL = "zLower" + character (len=*), parameter :: J_BND_ZU = "zUpper" + character (len=*), parameter :: J_BND_TYPE_PEC = "pec" character (len=*), parameter :: J_BND_TYPE_PMC = "pmc" diff --git a/test/smbjson/CMakeLists.txt b/test/smbjson/CMakeLists.txt index 8b045393..df6495f0 100644 --- a/test/smbjson/CMakeLists.txt +++ b/test/smbjson/CMakeLists.txt @@ -9,10 +9,13 @@ add_library (smbjson_test_fortran "test_mesh.F90" "test_parser.F90" "test_read_planewave.F90" + "test_read_dielectricSlab.F90" + "test_read_thinSlot.F90" + "test_read_sgbc.F90" "test_read_holland1981.F90" "test_read_towelHanger.F90" "test_read_connectedWires.F90" - "test_read_currentinjection.F90" + "test_read_currentInjection.F90" "test_read_shieldedPair.F90" "test_read_mtln.F90" "test_read_sphere.F90" diff --git a/test/smbjson/smbjson_testingTools.F90 b/test/smbjson/smbjson_testingTools.F90 index 9460d3ff..79bb42b9 100644 --- a/test/smbjson/smbjson_testingTools.F90 +++ b/test/smbjson/smbjson_testingTools.F90 @@ -37,10 +37,11 @@ subroutine expect_eq(err, ex, pr, ignoreRegions) if (checkRegions) then if (.not. ex%pecRegs == pr%pecRegs) call testFails(err, 'Expected and read "pec regions" do not match') if (.not. ex%pmcRegs == pr%pmcRegs) call testFails(err, 'Expected and read "pmc regions" do not match') + if (.not. ex%dielRegs == pr%dielRegs) call testFails(err, 'Expected and read "dielectric regions" do not match') + if (.not. ex%lossyThinSurfs == pr%lossyThinSurfs) call testFails(err, 'Expected and read "lossy thin surfaces" do not match') end if ! Sources - ! if (.not. ex%boxSrc == pr%boxSrc) call testFails(err, 'Expected and read "box sources" do not match') if (.not. ex%plnSrc == pr%plnSrc) call testFails(err, 'Expected and read "planewave sources" do not match') if (.not. ex%nodSrc == pr%nodSrc) call testFails(err, 'Expected and read "nodal sources" do not match') @@ -49,7 +50,9 @@ subroutine expect_eq(err, ex, pr, ignoreRegions) if (.not. ex%sonda == pr%sonda) call testFails(err, 'Expected and read "new probes" do not match') if (.not. ex%BloquePrb == pr%BloquePrb) call testFails(err, 'Expected and read "block probes" do not match') if (.not. ex%VolPrb == pr%VolPrb) call testFails(err, 'Expected and read "vol probes" do not match') + ! Thin elements + if (.not. ex%tSlots == pr%tSlots) call testFails(err, 'Expected and read "thin slots" do not match') if (.not. ex%tWires == pr%tWires) call testFails(err, 'Expected and read "thin wires" do not match') if (.not. ex%mtln == pr%mtln) call testFails(err, 'Expected and read mtln types do not match') if (err == 0) write(*,*) "Read and expected inputs are equal." diff --git a/test/smbjson/smbjson_tests.h b/test/smbjson/smbjson_tests.h index ae1ad59a..0052e5a3 100644 --- a/test/smbjson/smbjson_tests.h +++ b/test/smbjson/smbjson_tests.h @@ -13,6 +13,9 @@ extern "C" int test_parser_ctor(); extern "C" int test_parser_read_mesh(); extern "C" int test_read_planewave(); +extern "C" int test_read_sgbc(); +extern "C" int test_read_dielectricslab(); +extern "C" int test_read_thinslot(); extern "C" int test_read_holland1981(); extern "C" int test_read_towelhanger(); extern "C" int test_read_connectedwires(); @@ -35,6 +38,9 @@ TEST(smbjson, mesh_polyline_to_linel) { EXPECT_EQ(0, test_mesh_polyline_to_li TEST(smbjson, parser_ctor) { EXPECT_EQ(0, test_parser_ctor()); } TEST(smbjson, parser_read_mesh) { EXPECT_EQ(0, test_parser_read_mesh()); } TEST(smbjson, read_planewave) { EXPECT_EQ(0, test_read_planewave()); } +TEST(smbjson, read_dielectricslab) { EXPECT_EQ(0, test_read_dielectricslab()); } +TEST(smbjson, read_thinslot) { EXPECT_EQ(0, test_read_thinslot()); } +TEST(smbjson, read_sgbc) { EXPECT_EQ(0, test_read_sgbc()); } TEST(smbjson, read_holland1981) { EXPECT_EQ(0, test_read_holland1981()); } TEST(smbjson, read_towelhanger) { EXPECT_EQ(0, test_read_towelhanger()); } TEST(smbjson, read_connectedwires) { EXPECT_EQ(0, test_read_connectedwires()); } diff --git a/test/smbjson/test_idchildtable.F90 b/test/smbjson/test_idchildtable.F90 index 9e1f2008..5d63cb79 100644 --- a/test/smbjson/test_idchildtable.F90 +++ b/test/smbjson/test_idchildtable.F90 @@ -55,7 +55,7 @@ integer function test_idchildtable() bind(C) result(err) tbl = IdChildTable_t(core, root, J_MATERIALS) - if (tbl%count() /= 2) err = err + 1 + if (tbl%totalSize() /= 2) err = err + 1 block character (len=:), allocatable :: matType logical :: found diff --git a/test/smbjson/test_mesh.F90 b/test/smbjson/test_mesh.F90 index 4cac9913..b4f173c8 100644 --- a/test/smbjson/test_mesh.F90 +++ b/test/smbjson/test_mesh.F90 @@ -101,8 +101,8 @@ integer function test_mesh_add_get_long_list() bind(C) result(error_cnt) if (.not. found) error_cnt = error_cnt + 1 if (any(obtained%position /= expected%position)) error_cnt = error_cnt + 1 end block - - call mesh%printCoordHashInfo() + + ! call mesh%printCoordHashInfo() !! For debugging only end function diff --git a/test/smbjson/test_parser.F90 b/test/smbjson/test_parser.F90 index 1f95a1b1..88b4c59b 100644 --- a/test/smbjson/test_parser.F90 +++ b/test/smbjson/test_parser.F90 @@ -84,7 +84,7 @@ integer function test_parser_read_mesh() bind(C) result(err) parser = parser_t(filename) mesh = parser%readMesh() - call mesh%printCoordHashInfo() + ! call mesh%printCoordHashInfo() !! For debugging only expected%position = [10,2,1] obtained = mesh%getCoordinate(59, found) diff --git a/test/smbjson/test_read_connectedWires.F90 b/test/smbjson/test_read_connectedWires.F90 index a0b0cd2c..fd25b3d0 100644 --- a/test/smbjson/test_read_connectedWires.F90 +++ b/test/smbjson/test_read_connectedWires.F90 @@ -74,7 +74,7 @@ function expectedProblemDescription() result (expected) expected%pecRegs%Surfs(1)%Ytrancos = 1 expected%pecRegs%Surfs(1)%Ztrancos = 1 expected%pecRegs%Surfs(1)%Or = 3 - expected%pecRegs%Surfs(1)%tag = trim(adjustl(" ")) + expected%pecRegs%Surfs(1)%tag = "aluminum@ground_plane" ! Expected probes ! sonda diff --git a/test/smbjson/test_read_currentinjection.F90 b/test/smbjson/test_read_currentInjection.F90 similarity index 97% rename from test/smbjson/test_read_currentinjection.F90 rename to test/smbjson/test_read_currentInjection.F90 index 355c41ed..edd19c66 100644 --- a/test/smbjson/test_read_currentinjection.F90 +++ b/test/smbjson/test_read_currentInjection.F90 @@ -64,7 +64,7 @@ function expectedProblemDescription() result (expected) allocate(expected%pecRegs%Surfs(1)) allocate(expected%pecRegs%Lins(1)) - ! PEC square + ! Body expected%pecRegs%Surfs(1)%Or = +iEz expected%pecRegs%Surfs(1)%Xi = 5 expected%pecRegs%Surfs(1)%Xe = 14 @@ -72,7 +72,7 @@ function expectedProblemDescription() result (expected) expected%pecRegs%Surfs(1)%Ye = 14 expected%pecRegs%Surfs(1)%Zi = 10 expected%pecRegs%Surfs(1)%Ze = 10 - expected%pecRegs%Surfs(1)%tag = '' + expected%pecRegs%Surfs(1)%tag = 'aluminum@body' ! Exit line expected%pecRegs%Lins(1)%Or = +iEy @@ -82,7 +82,7 @@ function expectedProblemDescription() result (expected) expected%pecRegs%Lins(1)%Ye = 19 expected%pecRegs%Lins(1)%Zi = 10 expected%pecRegs%Lins(1)%Ze = 10 - expected%pecRegs%Lins(1)%tag = '' + expected%pecRegs%Lins(1)%tag = 'aluminum@exit' ! Expected sources. expected%nodSrc%n_nodSrc = 1 diff --git a/test/smbjson/test_read_dielectricSlab.F90 b/test/smbjson/test_read_dielectricSlab.F90 new file mode 100644 index 00000000..2313e503 --- /dev/null +++ b/test/smbjson/test_read_dielectricSlab.F90 @@ -0,0 +1,148 @@ +integer function test_read_dielectricslab() bind (C) result(err) + use smbjson + use smbjson_testingTools + + implicit none + + character(len=*), parameter :: filename = PATH_TO_TEST_DATA//'cases/dielectric_slab.fdtd.json' + type(Parseador) :: pr, ex + type(parser_t) :: parser + logical :: areSame + err = 0 + + ex = expectedProblemDescription() + parser = parser_t(filename) + pr = parser%readProblemDescription() + call expect_eq(err, ex, pr) + +contains + function expectedProblemDescription() result (expected) + type(Parseador) :: expected + integer :: i + + call initializeProblemDescription(expected) + + ! Expected general info. + expected%general%dt = 10e-12 + expected%general%nmax = 2000 + + ! Excected media matrix. + expected%matriz%totalX = 4 + expected%matriz%totalY = 4 + expected%matriz%totalZ = 50 + + ! Expected grid. + expected%despl%nX = 4 + expected%despl%nY = 4 + expected%despl%nZ = 50 + + allocate(expected%despl%desX(4)) + allocate(expected%despl%desY(4)) + allocate(expected%despl%desZ(50)) + expected%despl%desX = 0.1 + expected%despl%desY = 0.1 + expected%despl%desZ = 0.1 + expected%despl%mx1 = 0 + expected%despl%mx2 = 4 + expected%despl%my1 = 0 + expected%despl%my2 = 4 + expected%despl%mz1 = 0 + expected%despl%mz2 = 50 + + ! Expected boundaries. + expected%front%tipoFrontera(F_XL) = F_PEC + expected%front%tipoFrontera(F_XU) = F_PEC + expected%front%tipoFrontera(F_YL) = F_PMC + expected%front%tipoFrontera(F_YU) = F_PMC + expected%front%tipoFrontera(F_ZL) = F_PML + expected%front%tipoFrontera(F_ZU) = F_PML + + ! Expected sources. + allocate(expected%plnSrc%collection(1)) + expected%plnSrc%collection(1)%nombre_fichero = "gauss.exc" + expected%plnSrc%collection(1)%atributo = "" + expected%plnSrc%collection(1)%coor1 = [0, 0, 2] + expected%plnSrc%collection(1)%coor2 = [3, 3, 47] + expected%plnSrc%collection(1)%theta = 0.0 + expected%plnSrc%collection(1)%phi = 0.0 + expected%plnSrc%collection(1)%alpha = 1.5708 + expected%plnSrc%collection(1)%beta = 0.0 + expected%plnSrc%collection(1)%isRC=.false. + expected%plnSrc%collection(1)%nummodes=1 + expected%plnSrc%collection(1)%INCERTMAX=0.0 + expected%plnSrc%nc = 1 + expected%plnSrc%nC_max = 1 + + ! dielectric slab region + expected%dielRegs%nVols = 1 + expected%dielRegs%nSurfs = 0 + expected%dielRegs%nLins = 0 + expected%dielRegs%nVols_max = 1 + expected%dielRegs%nSurfs_max = 0 + allocate(expected%dielRegs%Vols(1)) + allocate(expected%dielRegs%Surfs(0)) + allocate(expected%dielRegs%Lins(0)) + ! slab + allocate(expected%dielRegs%vols(1)%c1P(0)) + allocate(expected%dielRegs%vols(1)%c2P(1)) + expected%dielRegs%vols(1)%n_C1P = 0 + expected%dielRegs%vols(1)%n_C2P = 1 + expected%dielRegs%vols(1)%sigma = 0.0 + expected%dielRegs%vols(1)%eps = 1.3*EPSILON_VACUUM + expected%dielRegs%vols(1)%mu = MU_VACUUM + expected%dielRegs%vols(1)%sigmam = 0.0 + expected%dielRegs%vols(1)%c2P%Or = 0 + expected%dielRegs%vols(1)%c2P%Xi = 0 + expected%dielRegs%vols(1)%c2P%Xe = 3 + expected%dielRegs%vols(1)%c2P%Yi = 0 + expected%dielRegs%vols(1)%c2P%Ye = 3 + expected%dielRegs%vols(1)%c2P%Zi = 20 + expected%dielRegs%vols(1)%c2P%Ze = 29 + expected%dielRegs%vols(1)%c2P%tag = 'teflon@slab' + + ! Expected probes + ! sonda + expected%Sonda%len_cor_max = 0 + expected%Sonda%length = 3 + expected%Sonda%length_max = 3 + allocate(expected%Sonda%collection(3)) + ! common data + do i = 1, 3 + expected%Sonda%collection(i)%type1 = NP_T1_PLAIN + expected%Sonda%collection(i)%type2 = NP_T2_TIME + expected%Sonda%collection(i)%filename = ' ' + expected%Sonda%collection(i)%tstart = 0.0 + expected%Sonda%collection(i)%tstop = 0.0 + expected%Sonda%collection(i)%tstep = 0.0 + expected%Sonda%collection(i)%fstart = 0.0 + expected%Sonda%collection(i)%fstop = 0.0 + expected%Sonda%collection(i)%fstep = 0.0 + allocate(expected%Sonda%collection(i)%cordinates(3)) + expected%Sonda%collection(i)%cordinates(1)%Or = NP_COR_EX + expected%Sonda%collection(i)%cordinates(2)%Or = NP_COR_EY + expected%Sonda%collection(i)%cordinates(3)%Or = NP_COR_EZ + expected%Sonda%collection(i)%len_cor = 3 + end do + ! point probe at front + expected%Sonda%collection(1)%outputrequest = "front" + expected%Sonda%collection(1)%cordinates(1:3)%tag = "front" + expected%Sonda%collection(1)%cordinates(1:3)%Xi = 2 + expected%Sonda%collection(1)%cordinates(1:3)%Yi = 2 + expected%Sonda%collection(1)%cordinates(1:3)%Zi = 10 + ! point probe in dielectric slab + expected%Sonda%collection(2)%outputrequest = "inner" + expected%Sonda%collection(2)%cordinates(1:3)%tag = "inner" + expected%Sonda%collection(2)%cordinates(1:3)%Xi = 2 + expected%Sonda%collection(2)%cordinates(1:3)%Yi = 2 + expected%Sonda%collection(2)%cordinates(1:3)%Zi = 25 + ! point probe at back + expected%Sonda%collection(3)%outputrequest = "back" + expected%Sonda%collection(3)%cordinates(1:3)%tag = "back" + expected%Sonda%collection(3)%cordinates(1:3)%Xi = 2 + expected%Sonda%collection(3)%cordinates(1:3)%Yi = 2 + expected%Sonda%collection(3)%cordinates(1:3)%Zi = 40 + + + end function +end function + diff --git a/test/smbjson/test_read_sgbc.F90 b/test/smbjson/test_read_sgbc.F90 new file mode 100644 index 00000000..9ae88d06 --- /dev/null +++ b/test/smbjson/test_read_sgbc.F90 @@ -0,0 +1,147 @@ +integer function test_read_sgbc() bind (C) result(err) + use smbjson + use smbjson_testingTools + + implicit none + + character(len=*), parameter :: filename = PATH_TO_TEST_DATA//'cases/sgbc.fdtd.json' + type(Parseador) :: pr, ex + type(parser_t) :: parser + logical :: areSame + err = 0 + + ex = expectedProblemDescription() + parser = parser_t(filename) + pr = parser%readProblemDescription() + call expect_eq(err, ex, pr) + +contains + function expectedProblemDescription() result (expected) + type(Parseador) :: expected + + call initializeProblemDescription(expected) + + ! Expected general info. + expected%general%dt = 10e-12 + expected%general%nmax = 2000 + + ! Excected media matrix. + expected%matriz%totalX = 10 + expected%matriz%totalY = 10 + expected%matriz%totalZ = 10 + + ! Expected grid. + expected%despl%nX = 10 + expected%despl%nY = 10 + expected%despl%nZ = 10 + + allocate(expected%despl%desX(10)) + allocate(expected%despl%desY(10)) + allocate(expected%despl%desZ(10)) + expected%despl%desX = 0.1 + expected%despl%desY = 0.1 + expected%despl%desZ = 0.1 + expected%despl%mx1 = 0 + expected%despl%mx2 = 10 + expected%despl%my1 = 0 + expected%despl%my2 = 10 + expected%despl%mz1 = 0 + expected%despl%mz2 = 10 + + ! Expected boundaries. + expected%front%tipoFrontera(:) = F_MUR + + ! Expected materials + !! PECs + expected%pecRegs%nSurfs = 1 + expected%pecRegs%nLins = 0 + expected%pecRegs%nVols_max = 0 + expected%pecRegs%nSurfs_max = 1 + expected%pecRegs%nLins_max = 0 + allocate(expected%pecRegs%Vols(0)) + allocate(expected%pecRegs%Surfs(1)) + + !!! 2x2 PEC square + expected%pecRegs%Surfs(1)%Or = +iEz + expected%pecRegs%Surfs(1)%Xi = 3 + expected%pecRegs%Surfs(1)%Xe = 4 + expected%pecRegs%Surfs(1)%Yi = 3 + expected%pecRegs%Surfs(1)%Ye = 4 + expected%pecRegs%Surfs(1)%Zi = 3 + expected%pecRegs%Surfs(1)%Ze = 3 + expected%pecRegs%Surfs(1)%tag = 'material1@layer1' + + !! Composites + allocate(expected%lossyThinSurfs%cs(2)) + expected%lossyThinSurfs%length = 2 + expected%lossyThinSurfs%length_max = 2 + expected%lossyThinSurfs%nC_max = 2 + + !!! 2-layer composite + allocate(expected%lossyThinSurfs%cs(1)%c(1)) + expected%lossyThinSurfs%cs(1)%nc = 1 + expected%lossyThinSurfs%cs(1)%c(1)%tag = '2-layers-composite@layer2' + expected%lossyThinSurfs%cs(1)%c(1)%Or = +iEy + expected%lossyThinSurfs%cs(1)%c(1)%Xi = 3 + expected%lossyThinSurfs%cs(1)%c(1)%Xe = 4 + expected%lossyThinSurfs%cs(1)%c(1)%Yi = 3 + expected%lossyThinSurfs%cs(1)%c(1)%Ye = 3 + expected%lossyThinSurfs%cs(1)%c(1)%Zi = 3 + expected%lossyThinSurfs%cs(1)%c(1)%Ze = 4 + expected%lossyThinSurfs%cs(1)%numcapas = 2 + allocate(expected%lossyThinSurfs%cs(1)%thk(2)) + allocate(expected%lossyThinSurfs%cs(1)%sigma(2)) + allocate(expected%lossyThinSurfs%cs(1)%eps(2)) + allocate(expected%lossyThinSurfs%cs(1)%mu(2)) + allocate(expected%lossyThinSurfs%cs(1)%sigmam(2)) + expected%lossyThinSurfs%cs(1)%thk = [ 1e-3, 5e-3] + expected%lossyThinSurfs%cs(1)%sigma = [ 2e-4, 0.0] + expected%lossyThinSurfs%cs(1)%eps = [1.3*EPSILON_VACUUM, 1.3*EPSILON_VACUUM] + expected%lossyThinSurfs%cs(1)%mu = [ MU_VACUUM, MU_VACUUM] + expected%lossyThinSurfs%cs(1)%sigmam = [ 0.0, 0.0] + allocate(expected%lossyThinSurfs%cs(1)%thk_devia(2)) + allocate(expected%lossyThinSurfs%cs(1)%sigma_devia(2)) + allocate(expected%lossyThinSurfs%cs(1)%eps_devia(2)) + allocate(expected%lossyThinSurfs%cs(1)%mu_devia(2)) + allocate(expected%lossyThinSurfs%cs(1)%sigmam_devia(2)) + expected%lossyThinSurfs%cs(1)%thk_devia(:) = 0.0 + expected%lossyThinSurfs%cs(1)%sigma_devia(:) = 0.0 + expected%lossyThinSurfs%cs(1)%eps_devia(:) = 0.0 + expected%lossyThinSurfs%cs(1)%mu_devia(:) = 0.0 + expected%lossyThinSurfs%cs(1)%sigmam_devia(:) = 0.0 + + !!! 3-layer composite + allocate(expected%lossyThinSurfs%cs(2)%c(1)) + expected%lossyThinSurfs%cs(2)%nc = 1 + expected%lossyThinSurfs%cs(2)%c(1)%tag = '3-layers-composite@layer3' + expected%lossyThinSurfs%cs(2)%c(1)%Or = +iEx + expected%lossyThinSurfs%cs(2)%c(1)%Xi = 3 + expected%lossyThinSurfs%cs(2)%c(1)%Xe = 3 + expected%lossyThinSurfs%cs(2)%c(1)%Yi = 3 + expected%lossyThinSurfs%cs(2)%c(1)%Ye = 4 + expected%lossyThinSurfs%cs(2)%c(1)%Zi = 3 + expected%lossyThinSurfs%cs(2)%c(1)%Ze = 4 + expected%lossyThinSurfs%cs(2)%numcapas = 3 + allocate(expected%lossyThinSurfs%cs(2)%thk(3)) + allocate(expected%lossyThinSurfs%cs(2)%sigma(3)) + allocate(expected%lossyThinSurfs%cs(2)%eps(3)) + allocate(expected%lossyThinSurfs%cs(2)%mu(3)) + allocate(expected%lossyThinSurfs%cs(2)%sigmam(3)) + expected%lossyThinSurfs%cs(2)%thk = [ 1e-3, 5e-3, 1e-3] + expected%lossyThinSurfs%cs(2)%sigma = [ 2e-4, 0.0, 0.0] + expected%lossyThinSurfs%cs(2)%eps = [EPSILON_VACUUM, EPSILON_VACUUM, EPSILON_VACUUM] + expected%lossyThinSurfs%cs(2)%mu = [ MU_VACUUM, 1.3*MU_VACUUM, MU_VACUUM] + expected%lossyThinSurfs%cs(2)%sigmam = [ 0.0, 0.0, 1e-4] + allocate(expected%lossyThinSurfs%cs(2)%thk_devia(3)) + allocate(expected%lossyThinSurfs%cs(2)%sigma_devia(3)) + allocate(expected%lossyThinSurfs%cs(2)%eps_devia(3)) + allocate(expected%lossyThinSurfs%cs(2)%mu_devia(3)) + allocate(expected%lossyThinSurfs%cs(2)%sigmam_devia(3)) + expected%lossyThinSurfs%cs(2)%thk_devia(:) = 0.0 + expected%lossyThinSurfs%cs(2)%sigma_devia(:) = 0.0 + expected%lossyThinSurfs%cs(2)%eps_devia(:) = 0.0 + expected%lossyThinSurfs%cs(2)%mu_devia(:) = 0.0 + expected%lossyThinSurfs%cs(2)%sigmam_devia(:) = 0.0 + end function +end function + diff --git a/test/smbjson/test_read_thinSlot.F90 b/test/smbjson/test_read_thinSlot.F90 new file mode 100644 index 00000000..1fa5b8e8 --- /dev/null +++ b/test/smbjson/test_read_thinSlot.F90 @@ -0,0 +1,150 @@ +integer function test_read_thinSlot() bind (C) result(err) + use smbjson + use smbjson_testingTools + + implicit none + + character(len=*), parameter :: filename = PATH_TO_TEST_DATA//'cases/thinSlot.fdtd.json' + type(Parseador) :: pr, ex + type(parser_t) :: parser + logical :: areSame + err = 0 + + ex = expectedProblemDescription() + parser = parser_t(filename) + pr = parser%readProblemDescription() + call expect_eq(err, ex, pr) + +contains + function expectedProblemDescription() result (expected) + type(Parseador) :: expected + integer :: i + + call initializeProblemDescription(expected) + + ! Expected general info. + expected%general%dt = 10e-12 + expected%general%nmax = 2000 + + ! Excected media matrix. + expected%matriz%totalX = 4 + expected%matriz%totalY = 4 + expected%matriz%totalZ = 50 + + ! Expected grid. + expected%despl%nX = 4 + expected%despl%nY = 4 + expected%despl%nZ = 50 + + allocate(expected%despl%desX(4)) + allocate(expected%despl%desY(4)) + allocate(expected%despl%desZ(50)) + expected%despl%desX = 0.1 + expected%despl%desY = 0.1 + expected%despl%desZ = 0.1 + expected%despl%mx1 = 0 + expected%despl%mx2 = 4 + expected%despl%my1 = 0 + expected%despl%my2 = 4 + expected%despl%mz1 = 0 + expected%despl%mz2 = 50 + + ! Expected boundaries. + expected%front%tipoFrontera(F_XL) = F_PER + expected%front%tipoFrontera(F_XU) = F_PER + expected%front%tipoFrontera(F_YL) = F_PER + expected%front%tipoFrontera(F_YU) = F_PER + expected%front%tipoFrontera(F_ZL) = F_PML + expected%front%tipoFrontera(F_ZU) = F_PML + + ! Expected sources. + allocate(expected%plnSrc%collection(1)) + expected%plnSrc%collection(1)%nombre_fichero = "gauss.exc" + expected%plnSrc%collection(1)%atributo = "" + expected%plnSrc%collection(1)%coor1 = [0, 0, 2] + expected%plnSrc%collection(1)%coor2 = [3, 3, 47] + expected%plnSrc%collection(1)%theta = 0.0 + expected%plnSrc%collection(1)%phi = 0.0 + expected%plnSrc%collection(1)%alpha = 1.5708 + expected%plnSrc%collection(1)%beta = 0.0 + expected%plnSrc%collection(1)%isRC=.false. + expected%plnSrc%collection(1)%nummodes=1 + expected%plnSrc%collection(1)%INCERTMAX=0.0 + expected%plnSrc%nc = 1 + expected%plnSrc%nC_max = 1 + + ! materials + !! pec square + expected%pecRegs%nVols = 0 + expected%pecRegs%nSurfs = 1 + expected%pecRegs%nLins = 0 + expected%pecRegs%nVols_max = 0 + expected%pecRegs%nSurfs_max = 1 + expected%pecRegs%nLins_max = 0 + allocate(expected%pecRegs%Vols(0)) + allocate(expected%pecRegs%Surfs(1)) + allocate(expected%pecRegs%Lins(0)) + expected%pecRegs%Surfs(1)%Or = +iEz + expected%pecRegs%Surfs(1)%Xi = 0 + expected%pecRegs%Surfs(1)%Xe = 3 + expected%pecRegs%Surfs(1)%Yi = 0 + expected%pecRegs%Surfs(1)%Ye = 3 + expected%pecRegs%Surfs(1)%Zi = 25 + expected%pecRegs%Surfs(1)%Ze = 25 + expected%pecRegs%Surfs(1)%tag = 'copper@square' + + !! thin slot + expected%tSlots%n_tg = 1 + allocate(expected%tslots%tg(1)) + expected%tSlots%tg(1)%width = 3e-3 + expected%tSlots%tg(1)%n_tgc = 2 + allocate(expected%tSlots%tg(1)%tgc(2)) + expected%tSlots%tg(1)%tgc(1)%i = 1 + expected%tSlots%tg(1)%tgc(1)%j = 2 + expected%tSlots%tg(1)%tgc(1)%k = 25 + expected%tSlots%tg(1)%tgc(1)%node = 0 + expected%tSlots%tg(1)%tgc(1)%dir = iEx + expected%tSlots%tg(1)%tgc(1)%Or = -1 + expected%tSlots%tg(1)%tgc(1)%tag = "3mm-gap@slot" + expected%tSlots%tg(1)%tgc(2) = expected%tSlots%tg(1)%tgc(1) + expected%tSlots%tg(1)%tgc(2)%i = 2 + + ! Expected probes + ! sonda + expected%Sonda%len_cor_max = 0 + expected%Sonda%length = 2 + expected%Sonda%length_max = 2 + allocate(expected%Sonda%collection(2)) + ! common data + do i = 1, 2 + expected%Sonda%collection(i)%type1 = NP_T1_PLAIN + expected%Sonda%collection(i)%type2 = NP_T2_TIME + expected%Sonda%collection(i)%filename = ' ' + expected%Sonda%collection(i)%tstart = 0.0 + expected%Sonda%collection(i)%tstop = 0.0 + expected%Sonda%collection(i)%tstep = 0.0 + expected%Sonda%collection(i)%fstart = 0.0 + expected%Sonda%collection(i)%fstop = 0.0 + expected%Sonda%collection(i)%fstep = 0.0 + allocate(expected%Sonda%collection(i)%cordinates(3)) + expected%Sonda%collection(i)%cordinates(1)%Or = NP_COR_EX + expected%Sonda%collection(i)%cordinates(2)%Or = NP_COR_EY + expected%Sonda%collection(i)%cordinates(3)%Or = NP_COR_EZ + expected%Sonda%collection(i)%len_cor = 3 + end do + ! point probe at front + expected%Sonda%collection(1)%outputrequest = "front" + expected%Sonda%collection(1)%cordinates(1:3)%tag = "front" + expected%Sonda%collection(1)%cordinates(1:3)%Xi = 2 + expected%Sonda%collection(1)%cordinates(1:3)%Yi = 2 + expected%Sonda%collection(1)%cordinates(1:3)%Zi = 10 + ! point probe at back + expected%Sonda%collection(2)%outputrequest = "back" + expected%Sonda%collection(2)%cordinates(1:3)%tag = "back" + expected%Sonda%collection(2)%cordinates(1:3)%Xi = 2 + expected%Sonda%collection(2)%cordinates(1:3)%Yi = 2 + expected%Sonda%collection(2)%cordinates(1:3)%Zi = 40 + + end function +end function + diff --git a/test/smbjson/test_read_towelHanger.F90 b/test/smbjson/test_read_towelHanger.F90 index a12cc61f..3548ba2c 100644 --- a/test/smbjson/test_read_towelHanger.F90 +++ b/test/smbjson/test_read_towelHanger.F90 @@ -74,7 +74,7 @@ function expectedProblemDescription() result (expected) expected%pecRegs%Surfs(1)%Ytrancos = 1 expected%pecRegs%Surfs(1)%Ztrancos = 1 expected%pecRegs%Surfs(1)%Or = 3 - expected%pecRegs%Surfs(1)%tag = trim(adjustl(" ")) + expected%pecRegs%Surfs(1)%tag = "copper@ground_plane" ! Expected probes ! sonda diff --git a/testData/cases/connectedWires.fdtd.json b/testData/cases/connectedWires.fdtd.json index eb549f47..8fe95f1e 100644 --- a/testData/cases/connectedWires.fdtd.json +++ b/testData/cases/connectedWires.fdtd.json @@ -35,6 +35,7 @@ "terminations": [{"type": "short"}] }, { + "name": "aluminum", "id": 4, "type": "pec" } @@ -55,7 +56,7 @@ "elements": [ {"id": 1, "type": "node", "coordinateIds": [1]}, {"id": 2, "type": "polyline", "coordinateIds": [1, 2, 5] }, - {"id": 3, "type": "cell", "intervals": [[[25, 20, 30], [45, 30, 30]]] }, + {"id": 3, "type": "cell", "name": "ground_plane", "intervals": [[[25, 20, 30], [45, 30, 30]]] }, {"id": 4, "type": "node", "coordinateIds": [4]}, {"id": 5, "type": "polyline", "coordinateIds": [5, 3, 4] }, {"id": 6, "type": "node", "coordinateIds": [5]} diff --git a/testData/cases/currentInjection.fdtd.json b/testData/cases/currentInjection.fdtd.json index 25a97c0d..9fa3a2d7 100644 --- a/testData/cases/currentInjection.fdtd.json +++ b/testData/cases/currentInjection.fdtd.json @@ -15,19 +15,18 @@ "steps": { "x": [0.1], "y": [0.1], "z": [0.1] } }, "elements": [ - {"id": 1, "type": "cell", "intervals": [ [[10, 0, 10], [10, 5, 10]] ]}, - {"id": 2, "type": "cell", "intervals": [ [[ 5, 5, 10], [15, 15, 10]] ]}, - {"id": 3, "type": "cell", "intervals": [ [[10, 15, 10], [10, 20, 10]] ]}, - {"id": 4, "type": "cell", "intervals": [ [[ 9, 2, 9], [11, 2, 11]] ]}, - {"id": 5, "type": "cell", "intervals": [ [[ 9, 17, 9], [11, 17, 11]] ]} + {"id": 1, "type": "cell", "name": "entry", "intervals": [ [[10, 0, 10], [10, 5, 10]] ]}, + {"id": 2, "type": "cell", "name": "body", "intervals": [ [[ 5, 5, 10], [15, 15, 10]] ]}, + {"id": 3, "type": "cell", "name": "exit", "intervals": [ [[10, 15, 10], [10, 20, 10]] ]}, + {"id": 4, "type": "cell", "name": "bulk_current_entry", "intervals": [ [[ 9, 2, 9], [11, 2, 11]] ]}, + {"id": 5, "type": "cell", "name": "bulk_current_exit", "intervals": [ [[ 9, 17, 9], [11, 17, 11]] ]} ] }, - "materials": [ {"id": 1, "type": "pec"} ], + "materials": [ {"id": 1, "type": "pec", "name": "aluminum"} ], "materialAssociations": [ - {"type": "bulk", "materialId": 1, "elementIds": [2]}, - {"type": "bulk", "materialId": 1, "elementIds": [3]} + {"type": "bulk", "materialId": 1, "elementIds": [2, 3]} ], "sources": [ diff --git a/testData/cases/dielectric_slab.fdtd.json b/testData/cases/dielectric_slab.fdtd.json new file mode 100644 index 00000000..872f73a7 --- /dev/null +++ b/testData/cases/dielectric_slab.fdtd.json @@ -0,0 +1,87 @@ +{ + "format": "FDTD Input file", + "__comments": "Planewave illuminating dielectric slab.", + + "general": { + "timeStep": 10e-12, + "numberOfSteps": 2000 + }, + + "boundary": { + "xLower": {"type": "pec"}, + "xUpper": {"type": "pec"}, + "yLower": {"type": "pmc"}, + "yUpper": {"type": "pmc"}, + "zLower": {"type": "pml"}, + "zUpper": {"type": "pml"} + }, + + "mesh": { + "grid": { + "numberOfCells": [4, 4, 50], + "steps": { "x": [0.1], "y": [0.1], "z": [0.1] } + }, + "coordinates": [ + {"id": 1, "relativePosition": [2, 2, 10]}, + {"id": 2, "relativePosition": [2, 2, 25]}, + {"id": 3, "relativePosition": [2, 2, 40]} + ], + "elements": [ + {"id": 1, "type": "node", "coordinateIds": [1]}, + {"id": 2, "type": "node", "coordinateIds": [2]}, + {"id": 3, "type": "node", "coordinateIds": [3]}, + {"id": 4, "type": "cell", "name": "pw-box", "intervals": [ [ [0, 0, 2], [4, 4, 48] ] ]}, + {"id": 5, "type": "cell", "name": "slab", "intervals": [ [ [0, 0, 20], [4, 4, 30] ] ]} + ] + }, + + "materials": [ + { + "name": "teflon", + "id": 1, + "type": "isotropic", + "relativePermittivity": 2.1 + } + ], + + "materialAssociations": [ + {"type": "bulk", "materialId": 1, "elementIds": [5]} + ], + + "sources": [ + { + "type": "planewave", + "magnitudeFile": "gauss.exc", + "elementIds": [4], + "direction": { + "theta": 0.0, + "phi": 0.0 + }, + "polarization": { + "theta": 1.5708, + "phi": 0.0 + } + } + ], + + "probes": [ + { + "name": "front", + "type": "point", + "field": "electric", + "elementIds": [1] + }, + { + "name": "inner", + "type": "point", + "field": "electric", + "elementIds": [2] + }, + { + "name": "back", + "type": "point", + "field": "electric", + "elementIds": [3] + } + ] +} \ No newline at end of file diff --git a/testData/cases/sgbc.fdtd.json b/testData/cases/sgbc.fdtd.json new file mode 100644 index 00000000..63c0cf48 --- /dev/null +++ b/testData/cases/sgbc.fdtd.json @@ -0,0 +1,69 @@ +{ + "format": "FDTD Input file", + "__comments": "Example input with sgbc material", + + "general": { + "timeStep": 10e-12, + "numberOfSteps": 2000 + }, + + "boundary": { + "all": {"type": "mur"} + }, + + "mesh": { + "grid": { + "numberOfCells": [10, 10, 10], + "steps": { "x": [0.1], "y": [0.1], "z": [0.1] } + }, + "elements": [ + {"id": 1, "type": "cell", "intervals": [ [ [3, 3, 3], [5, 5, 3] ] ]}, + {"id": 2, "type": "cell", "intervals": [ [ [3, 3, 3], [5, 3, 5] ] ]}, + {"id": 3, "type": "cell", "intervals": [ [ [3, 3, 3], [3, 5, 5] ] ]} + ] + }, + + "materials": [ + { + "type": "pec", + "id": 1 + }, + { + "name": "2-layers-composite", + "type": "multilayeredSurface", + "id": 2, + "layers": [ + {"thickness": 1e-3, "relativePermittivity": 1.3, "electricConductivity": 2e-4}, + {"thickness": 5e-3, "relativePermittivity": 1.3} + ] + }, + { + "name": "3-layers-composite", + "type": "multilayeredSurface", + "id": 3, + "layers": [ + {"thickness": 1e-3, "electricConductivity": 2e-4}, + {"thickness": 5e-3, "relativePermeability": 1.3}, + {"thickness": 1e-3, "magneticConductivity": 1e-4} + ] + } + ], + + "materialAssociations": [ + { + "type": "bulk", + "materialId": 1, + "elementIds": [ 1 ] + }, + { + "type": "surface", + "materialId": 2, + "elementIds": [ 2 ] + }, + { + "type": "surface", + "materialId": 3, + "elementIds": [ 3 ] + } + ] +} \ No newline at end of file diff --git a/testData/cases/thinSlot.fdtd.json b/testData/cases/thinSlot.fdtd.json new file mode 100644 index 00000000..510190bc --- /dev/null +++ b/testData/cases/thinSlot.fdtd.json @@ -0,0 +1,86 @@ +{ + "format": "FDTD Input file", + "__comments": "Planewave illuminating a thin slot.", + + "general": { + "timeStep": 10e-12, + "numberOfSteps": 2000 + }, + + "boundary": { + "xLower": {"type": "periodic"}, + "xUpper": {"type": "periodic"}, + "yLower": {"type": "periodic"}, + "yUpper": {"type": "periodic"}, + "zLower": {"type": "pml"}, + "zUpper": {"type": "pml"} + }, + + "mesh": { + "grid": { + "numberOfCells": [4, 4, 50], + "steps": { "x": [0.1], "y": [0.1], "z": [0.1] } + }, + "coordinates": [ + {"id": 1, "relativePosition": [2, 2, 10]}, + {"id": 2, "relativePosition": [2, 2, 40]} + ], + "elements": [ + {"id": 1, "type": "node", "coordinateIds": [1]}, + {"id": 2, "type": "node", "coordinateIds": [2]}, + {"id": 3, "type": "cell", "name": "pw-box", "intervals": [ [ [0, 0, 2], [4, 4, 48] ] ]}, + {"id": 4, "type": "cell", "name": "square", "intervals": [ [ [0, 0, 25], [4, 4, 25] ] ]}, + {"id": 5, "type": "cell", "name": "slot", "intervals": [ [ [1, 2, 25], [3, 2, 25] ] ]} + ] + }, + + "materials": [ + { + "name": "copper", + "id": 1, + "type": "pec" + }, + { + "name": "3mm-gap", + "type": "thinSlot", + "id": 2, + "width": 3e-3 + } + ], + + "materialAssociations": [ + {"type": "bulk", "materialId": 1, "elementIds": [4]}, + {"type": "line", "materialId": 2, "elementIds": [5]} + ], + + "sources": [ + { + "type": "planewave", + "magnitudeFile": "gauss.exc", + "elementIds": [3], + "direction": { + "theta": 0.0, + "phi": 0.0 + }, + "polarization": { + "theta": 1.5708, + "phi": 0.0 + } + } + ], + + "probes": [ + { + "name": "front", + "type": "point", + "field": "electric", + "elementIds": [1] + }, + { + "name": "back", + "type": "point", + "field": "electric", + "elementIds": [2] + } + ] +} \ No newline at end of file diff --git a/testData/cases/towelHanger.fdtd.json b/testData/cases/towelHanger.fdtd.json index 14f62848..4a83b382 100644 --- a/testData/cases/towelHanger.fdtd.json +++ b/testData/cases/towelHanger.fdtd.json @@ -38,6 +38,7 @@ "type": "short"}] }, { + "name": "copper", "id": 4, "type": "pec" } @@ -59,7 +60,7 @@ "elements": [ {"id": 1, "type": "node", "coordinateIds": [1]}, {"id": 2, "type": "polyline", "coordinateIds": [1, 2, 5, 3, 4] }, - {"id": 3, "type": "cell", "intervals": [[[25, 20, 30], [45, 30, 30]]] }, + {"id": 3, "type": "cell", "name": "ground_plane", "intervals": [[[25, 20, 30], [45, 30, 30]]] }, {"id": 4, "type": "node", "coordinateIds": [4]}, {"id": 5, "type": "cell", "intervals": [[[1, 1, 1], [59, 59, 59]]] }, {"id": 6, "type": "node", "coordinateIds": [5]}