UCVM 13.9.0 Developer Guide

From SCECpedia
Jump to navigationJump to search

Overview

This guide is intended for users looking to modify the UCVM source code, register new models with UCVM, or integrate UCVM into their own projects. Most common functionality, including mesh generation and getting material properties from models, is described in the main user guide.

Released on September 8th, 2013, UCVM 13.9.0 represents the second major release of the Unified Community Velocity Model (UCVM) framework. While at its core, UCVM is a collection of software utilities that are designed to make interacting with velocity models easier, it also includes a powerful API for interacting with or registering new velocity models. UCVM's API makes it very easy to integrate into software projects.

This guide will walk you through some of the common API functions and steps required to get UCVM to work either with your code or to have it work within your code.

Register a New Velocity Model

UCVM can be extended to query any velocity model provided that certain conditions are met. Every new velocity model must have at least:

Unless the model is packaged in e-tree format, implementing it will require code modifications to the core UCVM library located in ./src/ucvm and recompilation. The general steps are:

  • Define new model label UCVM_MODEL_MODELNAME in ucvm_dtypes.h
  • Create ucvm_model_modelname.h/.c containing the glue code that links the UCVM query interface to the native model interface
  • Modify ./src/ucvm/ucvm.c:
    • Add ucvm_model_modelname.h include at top
    • Add model lookup to ucvm_add_model() function
    • Add model to ucvm_get_resources() function
  • Modify ./src/ucvm/Makefile.am:
    • Add ucvm_model_modelname.o to list of libucvm.a dependencies
  • Modify ./configure.ac:
    • Define "enable-modelname", "with-modelname-lib-path", and "with-modelname-incl-path" configure options
    • Add library and header checks for your new model
  • Modify installer to customize path to your new model in ucvm.conf:
    • Add your new model to ./conf/Makefile.am
    • Add config entry for your new model to ./conf/ucvm_template.conf
  • Regenerate the Makefiles with ./scripts/autoconf/reconf.sh
  • Reconfigure and recompile UCVM, making sure to pass your new model flags to the configure utility

Query a Velocity Model in Your Code

C

Calling UCVM from C code is relatively trivial. Minimally, you need the UCVM library as well as "ucvm.h".

Using UCVM involves three fundamental steps: 1) Initializing UCVM through the ucvm_init function, 2) adding appropriate models through the ucvm_add_model function, and 3) retrieving material properties through the ucvm_query function. These functions are shown in the example below.

Example.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/time.h>
#include "ucvm.h"

int main(int argc, char **argv)
{
  int nn = 1;
  ucvm_point_t pnts;
  ucvm_data_t data;
  char cmb_label[UCVM_MAX_LABEL_LEN];

  printf("Init\n");
  if (ucvm_init("../conf/test/ucvm.conf") != UCVM_CODE_SUCCESS) {
    fprintf(stderr, "Init failed\n");
    return(1);
  }

  printf("Query Mode\n");
  if (ucvm_setparam(UCVM_PARAM_QUERY_MODE,
                    UCVM_COORD_GEO_DEPTH) != UCVM_CODE_SUCCESS) {
    fprintf(stderr, "Failed to set z mode\n");
    return(1);
  }

  printf("Add Crustal Model 1D\n");
  if (ucvm_add_model(UCVM_MODEL_1D) != UCVM_CODE_SUCCESS) {
    fprintf(stderr, "Retrieval of 1D failed\n");
    return(1);
  }

  printf("Add GTL Model Ely\n");
  if (ucvm_add_model(UCVM_MODEL_ELYGTL) != UCVM_CODE_SUCCESS) {
    fprintf(stderr, "Retrieval of Ely GTL failed\n");
    return(1);
  }

  /* Change GTL interpolation function from default (linear)
     to Ely interpolation */
  if (ucvm_assoc_ifunc(UCVM_MODEL_ELYGTL,
                       UCVM_IFUNC_ELY) != UCVM_CODE_SUCCESS) {
    fprintf(stderr,
            "Failed to associate interpolation function with Ely GTL\n");
    return(1);
  }

  /* Change interpolation z range from 0,0 to 0,350 */
  if (ucvm_setparam(UCVM_PARAM_IFUNC_ZRANGE, 0.0,
                    350.0) != UCVM_CODE_SUCCESS) {
    fprintf(stderr, "Failed to set interpolation range\n");
    return(1);
  }

  printf("Create point\n");
  pnts.coord[0] = -118.0;
  pnts.coord[1] = 34.0;
  pnts.coord[2] = 2000.0;

  printf("Query Model\n");
  if (ucvm_query(nn, &pnts, &data) != UCVM_CODE_SUCCESS) {
    fprintf(stderr, "Query UCVM failed\n");
    return(1);
  }

  /* Get cmb data label */
  ucvm_ifunc_label(data.cmb.source,
                   cmb_label, UCVM_MAX_LABEL_LEN);

  printf("Results:\n");
  printf("\tsource=%s, vp=%lf, vs=%lf, rho=%lf\n",
         cmb_label, data.cmb.vp, data.cmb.vs, data.cmb.rho);

  return(0);
}

Fortran

Calling UCVM using Fortran is a relatively trivial procedure. After you have installed UCVM as per this user guide, you must include the UCVM library, the Proj.4 library, the e-tree library, as well as any velocity model libraries that you have compiled into UCVM. For CVM-H, please note that there are actually two libraries required: lvxapi and lgeo. Because the default convention for calling C programs from Fortran automatically appends an underscore to the end of the function name, you must turn that off via a flag called "fno-underscoring". This will make the Fortran compiler try and find foo() instead of foo_().
As an example, suppose we have a Fortran file, example.f, that calls UCVM. We have compiled UCVM with CVM-S and CVM-H. The code to compile example.f would be as follows:

gfortran example.f -o ./example -L/path/to/ucvm-13.9.0/lib -L./path/to/ucvm-13.9.0/model/cvms4/lib -L/path/to/ucvm-13.9.0/model/cvmh1191/lib -L/path/to/ucvm-13.9.0/lib/proj-4/lib -L/path/to/ucvm-13.9.0/lib/euclid3/libsrc -lucvm -lcvms -lvxapi -lgeo -lproj -letree -fno-underscoring

The basic structure of how to call UCVM within Fortran is outlined in the example below.

Example.f

                program example
         
        c       UCVM Configuration Location
                CHARACTER(LEN=80) ucvmconf
        c       Model Name
                CHARACTER(LEN=4) model 
        c       Number of points we're passing to ucvm_query
                INTEGER pts      
         
        c       The UCVM point data structure. 
        c       coord(1) is longitude
        c       coord(2) is latitutde
        c       coord(3) is depth
                TYPE :: ucvm_point_t
                       REAL*8 coord(3)
                END TYPE ucvm_point_t
         
        c       Generic property structure
        c       Source is where it comes from
        c       vp is P-wave velocity in m/s
        c       vs is S-wave velocity in m/s
        c       rho is density in kg/m^3
                TYPE :: ucvm_prop_t
                        INTEGER source
                        REAL*8 vp
                        REAL*8 vs
                        REAL*8 rho
                END TYPE ucvm_prop_t
         
        c       Returned data structure
                TYPE :: ucvm_data_t
                        REAL*8 surf
                        REAL*8 vs30
                        REAL*8 depth
                        INTEGER domain
                        REAL*8 shift_cr
                        REAL*8 shift_gtl
                        type(ucvm_prop_t) crust
                        type(ucvm_prop_t) gtl
                        type(ucvm_prop_t) cmb
                END TYPE ucvm_data_t
         
        c       For our example we'll query five points
                type(ucvm_point_t) point(5)
        c       And we'll get back five sets of material properties
                type(ucvm_data_t) returnData(5)
         
        c       Number of points is 5.
                pts = 5
         
        c       We'll start at -118, 34 at 0 depth and go down by 1000m
        c       each step
                do 10 i = 1, 5
                        point(i)%coord(1) = -118
                        point(i)%coord(2) = 34
                        point(i)%coord(3) = (i - 1) * 1000
        10      continue
         
        c       Where is our configuration file?
                ucvmconf = "/home/scec-01/davidgil/ucvm.conf" // CHAR(0)
         
        c       What model are we querying?
                model = "cvms"
         
        c       Initialize UCVM
                call ucvm_init(ucvmconf)
         
        c       Add the model to UCVM
                call ucvm_add_model(model)
         
        c       Query the model. Note that the number of points is passed
        c       by value, not reference.
                call ucvm_query(%VAL(pts), point, returnData)
         
                print *, model, " results for lon -118, lat 34"
         
        c       Print out the results.
                do 20 i = 1, 5
                        print *, "Depth ", (i - 1) * 1000
                        print *, "Vs ", returnData(i)%crust%vs 
                        print *, "Vp ", returnData(i)%crust%vp 
                        print *, "Rho ", returnData(i)%crust%rho
        20      continue
         
        c       Close UCVM now that we've queried the points 
                call ucvm_finalize()
         
                end

GCC Fortran 4.3+ is required for this example to work.

C Application Programming Interface

UCVM provides a programming interface for querying Vp, Vs, and rho from any user-defined model. The main UCVM interface is as follows:

#ifndef UCVM_H
#define UCVM_H

#include <stdarg.h>
#include "ucvm_dtypes.h"

/* Initializer */
int ucvm_init(const char *config);

/* Finalizer */
int ucvm_finalize();

/* Enable specific model(s), by string list, by label, or 
   by ucvm_model_t */
int ucvm_add_model_list(const char *list);
int ucvm_add_model(const char *label);
int ucvm_add_user_model(ucvm_model_t *m, ucvm_modelconf_t *conf);

/* Use specific map (elev, vs30) by label */
int ucvm_use_map(const char *label);

/* Associate specific interp func with GTL model, by label 
   or by ucvm_ifunc_t */
int ucvm_assoc_ifunc(const char *mlabel, const char *ilabel);
int ucvm_assoc_user_ifunc(const char *mlabel, ucvm_ifunc_t *ifunc);

/* Get label for a model */
int ucvm_model_label(int m, char *label, int len);

/* Get label for an interpolation function */
int ucvm_ifunc_label(int f, char *label, int len);

/* Get version for a model */
int ucvm_model_version(int m, char *ver, int len);

/* Set parameters (see ucvm_dtypes.h for valid param flags) */
int ucvm_setparam(ucvm_param_t param, ...);

/* Query underlying models */
int ucvm_query(int n, ucvm_point_t *pnt, ucvm_data_t *data);

/* Get info on installed models */
int ucvm_install_info(char *info, int len);

#endif

The general order of operations for using this interface is:

  • Initialization (ucvm_init())
  • Add models in order of preference using ucvm_add_model(). These may be either crustal or GTL models. See below for specific details.
  • Set any models-specific flags using ucvm_setparam. These will override any flags specified in ucvm.conf. For example, to enable the 1D background model with CVM-H through the API, execute the ucvm_setparam() function as follows:
ucvm_setparam(UCVM_PARAM_MODEL_CONF, UCVM_MODEL_CVMH, "USE_1D_BKG", "True");
  • If GTLs have been added:
    • Associate an interpolation function with each using ucvm_assoc_ifunc(). Otherwise, linear interpolation will be used.
    • Set an interpolation depth range using ucvm_setparam(UCVM_PARAM_IFUNC_ZRANGE, ...). Otherwise the interpolation range is set to 0,0.
  • Query points of interest with ucvm_query()
  • Finalization (ucvm_finalize())


Notes on enabling models:

  • Models are referenced either by a pre-defined string id or by a populated ucvm_model_t structure.
  • Multiple models may be registered, and they are queried in order of registration.
  • A helper function ucvm_add_model_list() is provided to quickly add multiple models. The string format is "gtl_model<:gtl_interp>,crustal_model,..." where "<:gtl_interp>" is an optional GTL interpolation function specification. For example, the string "elygtl:ely,cvmh" specifies the Ely GTL and CVM-H, adn the use of the Ely interpolation function to smooth between the GTL and crustal models.
  • Pre-defined models include: CVM-S, CVM-H, CenCal, Lin-Thurber, Rob Graves Cape Mendocino, 1D, Ely GTL, any SCEC Etree or patch listed in the UCVM configuration file. These models are enabled by calling ucvm_add_model() with their name string identifier as listed in either ucvm_dtypes.h (pre-defined) or in the UCVM configuration file (user-defined SCEC Etree, UCVM patch).
  • Most predefined model interfaces only support one model instance at a time. However, multiple Etrees and patches may be enabled. Etrees and patches are defined in the UCVM configuration file with the following commands:
# Etree definition and path to etree
usermodel1_interface=model_etree
usermodel1_modelpath=/home/...

# Patch definition and path to configuration file
usermodel2_interface=model_patch
usermodel2_modelpath=/home/...

where:
usermodel1/usermodel2 : replaced with desired string identifier for the etree/patch model
  • The programmer may also define their own models and integrate them into UCVM. A user model interface is defined by creating the init(), finalize(), getversion(), getlabel(), setparam(), and query() functions for the model interface, and populating the ucvm_model_t structure with these function pointers and some additional record keeping information. Configuration information for a specific model instance of that interface is placed in a ucvm_modelconf_t structure. Once a model is fully described with a ucvm_model_t interface and a ucvm_modelconf_t configuration, it can be registered for use with the ucvm_add_user_model() function and queried with the ucvm_query() function.


Data Type Descriptions

The full list of defined data types are listed in /include/ucvm_dtypes.h. The following is a general description of the useful application definitions:

Points are specified with a ucvm_point_t structure:

/* 3D point */
typedef struct ucvm_point_t 
{
  double coord[3];
} ucvm_point_t;


Return data is specified with a ucvm_data_t structure:

typedef struct ucvm_data_t 
{
  double surf; /* Elevation of free surface in meters */
  double vs30; /* Vs30 value in m/s */
  ucvm_domain_t domain;  /* Domain where the point lies: GTL model, interpolation zone, crustal model, none. */
  double shift_cr; /* Depth shift applied to point when querying crustal models. Only used when a GTL is enabled. */
  double shift_gtl; /* Depth shift applied to point when querying GTL models. Only used when a GTL is enabled. */
  ucvm_prop_t crust; /* Material properties from crustal model */
  ucvm_prop_t gtl; /* Material properties from GTL model */
  ucvm_prop_t cmb; /* Combined GTL/crustal material properties. This is the final property set that applications should reference. */
} ucvm_data_t;

where ucvm_prop_t is:

/* Material properties */
typedef struct ucvm_prop_t 
{
  int source; /* Model idenfitifer */
  double vp; /* Velocity in m/s */
  double vs; /* Velocity in m/s */
  double rho; /* Density in g/m^3 */
} ucvm_prop_t;


Model interfaces (both crustal and GTL) are defined with a ucvm_model_t structure:

/* Model */
typedef struct ucvm_model_t 
{
  ucvm_mtype_t mtype;
  int (*init)(int id, ucvm_region_t *r, const char *config);
  int (*finalize)();
  int (*getversion)(int id, char *ver, int len);
  int (*getlabel)(int id, char *ver, int len);
  int (*setparam)(int id, int param, ...);
  int (*query)(int id, ucvm_ctype_t cmode,
               int n, ucvm_point_t *pnt, 
               ucvm_data_t *data);
} ucvm_model_t;


Other Interfaces

2D Grid Interface

Provides an interface for generating 2D regular grids in any USGS map projection. Include the header "ucvm_grid.h" to use these functions.

/* Generate grid from projection and dimensions */
int ucvm_grid_gen(ucvm_proj_t *iproj, ucvm_trans_t *trans,
                  ucvm_proj_t *oproj,
                  ucvm_dim_t *dims, double spacing, 
                  ucvm_point_t *pnts);

/* Generate grid from projection and dimensions */
int ucvm_grid_gen_file(ucvm_proj_t *iproj, ucvm_trans_t *trans,
                       ucvm_proj_t *oproj,
                       ucvm_dim_t *dims, double spacing, 
                       const char *filename);

/* Convert point list from one projection to another */
int ucvm_grid_convert(ucvm_proj_t *iproj, 
                      ucvm_proj_t *oproj, 
                      size_t n, ucvm_point_t *pnts);

/* Convert point list from one projection to another */
int ucvm_grid_convert_file(ucvm_proj_t *iproj, 
                           ucvm_proj_t *oproj, 
                           size_t n, const char *filename);


Technical Implementation Details

SCEC CVM Etree Convention

Etree Model Format

  • Variable resolution based off of Vs, max supported frequency, and points per wavelength. The resolution at any particular region will be dependent upon the local Vs value (relation shown below). However, a minimum Vs at Etree creation will clamp the resolution to a maximum value regardless of how low the local Vs is found to be.
rez = vs / (ppwl * freq)

where:
vs: Vs at point of interest (m/s)
ppwl: points per wavelength
freq: max supported frequency (Hz)
  • Model data is referenced relative to free surface. Free surface is defined at air/ground, water/ground interface. UCVM topography and bathymetry can be used to determine if a point is in the air/water and default properties returned for those domains.
  • Stored properties are Vp, Vs, and density.


Etree Metadata Description

The Etree metadata tag describes the payload of the octants, the extents of the coverage region, and the map projection. It will have the following format, with fields delimited by vertical bars:

metatype_version|title|author|date|vs_min|max_freq|ppwl|format|proj.4_string|geo_origin|rot_angle|xyz_dims|xyz_ticks

where:
  metatype_version: "SCEC_CVM_V1" string of max length 64 chars
  title: free-format title string of max length 64 chars
  author: free-format author string of max length 64 chars
  date: YY/MM/DD date string
  vs_min: vs minimum used to determine max resolution
  max_freq: maximum supported frequency in Hz
  ppwl: Points per wavelength
  format: data format specification of octants. Uses string format: "name,data_type,size,units". eg: "vp,float,4,m/s;vs,float,4,m/s;rho,float,4,kg/m^3"
  proj.4_string: Proj.4 projection string, eg: "+proj=aeqd +lat_0=36.0 +lon_0=-120.0 +x_0=0.0 +y_0=0.0"
  geo_origin: Origin point of CVM region in geo coordinates, eg: "-129.25,41.0"
  rot_angle: Rotation angle of bounding box in degrees, eg "55.0"
  xyz_dims: Dimensions of bounding box in km, eg "1800,800,100"
  xyz_ticks: Number of ticks along each dimension


SCEC Patch Model Format

A patch model consists of five files: a configuration text file, and four binary files with the surface data. All of these files are automatically generated by the patchmodel utility. The sections below describe the file formats.


Configuration file

The patch model configuration file specifies the origin, dimensions, and map projection of the 3D region covered by the patch. An example follows:

# cvmh patch conf file

# Version
version=cvmh_p1_2011/05/24
# Projection
proj=+proj=aeqd +lat_0=36.0 +lon_0=-120.0 +x_0=0.0 +y_0=0.0
lon_0=-121.300000
lat_0=35.600000
rot=90.000000
# Spacing
spacing=250.000000
# Dimensions
x-size=550000.000000
y-size=50000.000000
z-size=112500.000000
# Paths to surface files
surf_0_0_path=/home/scec-00/USER/opt/aftershock/ucvm/model/patch/cvmh_p1_surf_0_0.bin
surf_1_0_path=/home/scec-00/USER/opt/aftershock/ucvm/model/patch/cvmh_p1_surf_1_0.bin
surf_0_1_path=/home/scec-00/USER/opt/aftershock/ucvm/model/patch/cvmh_p1_surf_0_1.bin
surf_1_1_path=/home/scec-00/USER/opt/aftershock/ucvm/model/patch/cvmh_p1_surf_1_1.bin


Surface Files

The surface file format is a 2D array of three floating point values: vp, vs, and density. The assignment of x versus y axis in each file is dependent on the orientation of the surface with respect to the box's origin point.


SCEC Map Etree Convention

Etree Model Format

  • 3D Etree with a single octant depth along Z-axis (effectively a 2D grid)
  • Fixed resolution based off of maximum desired grid spacing in grd2etree configuration.
  • Sampled with grid registration to allow smoothing of adjacent octants in UCVM.
  • Stored values at each grid point are: surface elevation (float), Vs30 (float).


Etree Metadata Description

The Etree metadata tag describes the payload of the octants, the extents of the coverage region, and the map projection. It will have the following format, with fields delimited by vertical bars:

metatype_version|title|author|date|spacing|format|proj.4_string|geo_origin|rot_angle|xy_dims|xyz_ticks

where:
  metatype_version: "SCEC_MAP_V1" string of max length 64 chars
  title: free-format title string of max length 64 chars
  author: free-format author string of max length 64 chars
  date: YY/MM/DD date string
  spacing: grid spacing in meters
  format: data format specification of octants. Uses string format: "name,data_type,size,units". eg: "surf,float,4,m/s;vs30,float,4,m/s;"
  proj.4_string: Proj.4 projection string, eg: "+proj=aeqd +lat_0=36.0 +lon_0=-120.0 +x_0=0.0 +y_0=0.0"
  geo_origin: Origin point of CVM region in geo coordinates, eg: "-129.25,41.0"
  rot_angle: Rotation angle of bounding box in degrees, eg "55.0"
  xy_dims: Dimensions of bounding box in km, eg "1800,800"
  xyz_ticks: Number of ticks along each dimension